Python编程通过懒属性提升性能

目录
  • 为什么需要懒加载
  • 如何使用懒加载
  • 最后的话

懒加载是一种编程范式,它推迟加载操作,直到不得不这样做。通常,当操作开销很大,需要耗费大量时间或空间时,惰性求值是首选实现。例如,在 Python 中,涉及惰性求值的最著名技术之一是生成器。生成器不是为迭代创建整个序列,而是懒惰地一次生成一个元素。

在 Python 世界之外,许多其他面向对象的编程语言,例如 Swift 和 Kotlin,都具有与对象相关的惰性求值。具体来说,你可以指定自定义实例对象的特定属性是惰性的,这意味着在显式访问这些属性之前不会创建这些属性。

为什么需要懒加载

在我们开始讨论懒属性之前,有些人可能想知道为什么它很重要,或者我们为什么要使用懒属性。

比如在社交网站中,一个功能是查看一个人的关注者,以列表的形式呈现。当我们点击一个用户时,我们可以在弹出窗口中查看该用户的个人资料。获取用户个人资料数据的操作可能很昂贵,不仅需要访问远程服务器,还需要将数据存储在内存中。

那么在编程实现时可以把关注者的个人资料作为懒属性,仅在点击特定用户名时才获取该属性。

这就是为什么我们需要懒属性。

如何使用懒加载

方法 1:

使用 @property

@property 是一个装饰器,可以将常规函数转化为属性,比如支持点符号访问。因此,严格来说,创建属性并不是真正创建懒属性本身。相反,它只是提供一个接口来简化数据处理的问题。让我们先看看下面的代码。

class User:
    def __init__(self):
        self._profile_data = None
    @property
    def profile_data(self):
        if self._profile_data is None:
            print("执行耗时操作...")
            self._profile_data = 'profile data'
        return self._profile_data
demo = User()
print("init done")
print(demo.profile_data)
#init done
#执行耗时操作...
#profile data

初始化完成后并不会执行耗时操作,对应的加载用户列表就不会觉得卡。只有在获取用户资料(点击操作)时,程序会先判断是否已经存在 _profile_data,没有才会执行耗时操作,如果有直接返回,大大提升了效率。

方法 2:

使用 __getattr__ 特殊方法

在 Python 中,名称前后有双下划线的函数称为魔术方法。__getattr__ 可以帮助我们实现懒属性。

对于自定义类,实例对象的属性保存在字典中,可以访问实例对象的 __dict__ 属性获取。值得注意的是,如果__dict__ 不包含指定的属性,Python 将会调用魔术方法 __getattr__,写个代码你就明白了:

class User:
    def __init__(self):
        self._profile_data = None
        self.name = 'None'
     def __getattr__(self, item):
        print("called __getattr__")
        if item == 'profile_data':
            if self._profile_data is None:
                print("执行耗时操作...")
                self._profile_data = 'profile data'
            return self._profile_data
 user = User()
print("init done")
print(user.__dict__)
print(user.profile_data)
print(user.__dict__)
print(user.name)

输出结果如下:

init done
{'_profile_data': None, 'name': 'None'}
called __getattr__
执行耗时操作...
profile data
{'_profile_data': 'profile data', 'name': 'None'}
None

和方法 1 一样,初始化完成后并不会执行耗时操作,我们在获取 profile_data 属性时,由于 profile_data 不在 __dict__ 中,因此会执行 __getattr__ 方法获取,而 name 在  __dict__ 获取 name 属性时根本就不会执行  __getattr__ 方法。

怎么判断一个属性是不是在 __dict__ 中呢,只要没有显式的定义该属性,或者使用 setattr 来设置属性,它就不会在 __dict__  中。

因此可以借助魔术方法 __getattr__ 来创建懒属性 profile_data。

需要注意,Python 还有一个类似的魔术方法 __getattribute__,与 __getattr__ 方法不同的是, 每次获取属性时都会调用 __getattribute__ 方法。

class User:
    def __init__(self):
        self._profile_data = None
        self.name = 'None'
    def __getattribute__(self, item):
        print("called __getattr__")
user = User()
print("init done")
print(user.profile_data)
print(user.name)

程序输出如下:

init done
called __getattr__
None
called __getattr__
None

此功能仅在你期望属性非常频繁地更改并且只有最新数据相关时才有用。在这些情况下,我们可以通过定义相关函数来实现效果。换句话说,我不建议你尝试使用它,因为很容易陷入无限递归循环。

最后的话

在本文中,我们重点讨论了在 Python 中实现懒属性的两种实用方法:一种使用 @property 装饰器,另一种使用 __getattr__ 特殊方法。

就我个人而言,我更喜欢使用属性装饰器,它更直接、更容易理解。但是,当你需要定义多个懒属性时,该 getattr 方法更好,因为它提供了一个集中的地方来管理这些懒属性。

以上就是Python编程通过懒属性提升性能的详细内容,更多关于Python懒属性提升性能的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python爬虫图片懒加载技术 selenium和PhantomJS解析

    一.什么是图片懒加载? - 案例分析:抓取站长素材http://sc.chinaz.com/中的图片数据 #!/usr/bin/env python # -*- coding:utf-8 -*- import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agen

  • python 性能提升的几种方法

    关于python 性能提升的一些方案. 一.函数调用优化(空间跨度,避免访问内存) 程序的优化核心点在于尽量减少操作跨度,包括代码执行时间上的跨度以及内存中空间跨度. 1.大数据求和,使用sum a = range(100000) %timeit -n 10 sum(a) 10 loops, best of 3: 3.15 ms per loop %%timeit ...: s = 0 ...: for i in a: ...: s += i ...: 100 loops, best of 3:

  • 提升Python程序性能的7个习惯

    掌握一些技巧,可尽量提高Python程序性能,也可以避免不必要的资源浪费. 1.使用局部变量 尽量使用局部变量代替全局变量:便于维护,提高性能并节省内存. 使用局部变量替换模块名字空间中的变量,例如 ls = os.linesep.一方面可以提高程序性能,局部变量查找速度更快:另一方面可用简短标识符替代冗长的模块变量,提高可读性. 2.减少函数调用次数 对象类型判断时,采用isinstance()最优,采用对象类型身份(id())次之,采用对象值(type())比较最次. 判断变量num是否为整

  • python正则表达式的懒惰匹配和贪婪匹配说明

    第一次碰到这个问题的时候,确实不知道该怎么办,后来请教了一个大神,加上自己的理解,才了解是什么意思,这个东西写python的会经常用到,而且会特别频繁,在此写一篇博客,希望可以帮到一些朋友. 例:一个字符串 "abcdacsdnd" ①懒惰匹配 regex = "a.*?d" ②贪婪匹配 regex = "a.*d" 测试代码: # coding=UTF-8 import re str = "abcdacsdn" print(

  • Python编程通过懒属性提升性能

    目录 为什么需要懒加载 如何使用懒加载 最后的话 懒加载是一种编程范式,它推迟加载操作,直到不得不这样做.通常,当操作开销很大,需要耗费大量时间或空间时,惰性求值是首选实现.例如,在 Python 中,涉及惰性求值的最著名技术之一是生成器.生成器不是为迭代创建整个序列,而是懒惰地一次生成一个元素. 在 Python 世界之外,许多其他面向对象的编程语言,例如 Swift 和 Kotlin,都具有与对象相关的惰性求值.具体来说,你可以指定自定义实例对象的特定属性是惰性的,这意味着在显式访问这些属性

  • Python编程中的反模式实例分析

    本文实例讲述了Python编程中的反模式.分享给大家供大家参考.具体分析如下: Python是时下最热门的编程语言之一了.简洁而富有表达力的语法,两三行代码往往就能解决十来行C代码才能解决的问题:丰富的标准库和第三方库,大大节约了开发时间,使它成为那些对性能没有严苛要求的开发任务的首选:强大而活跃的社区,齐全的文档,也使很多编程的初学者选择了它作为自己的第一门编程语言.甚至有国外的报道称,Python已经成为了美国顶尖大学里最受欢迎的编程入门教学语言. 要学好一门编程语言实属不易,在初学阶段,就

  • Python异常对代码运行性能的影响实例解析

    前言 Python的异常处理能力非常强大,但是用不好也会带来负面的影响.我平时写程序的过程中也喜欢使用异常,虽然采取防御性的方式编码会更好,但是交给异常处理会起到偷懒作用.偶尔会想想异常处理会对性能造成多大的影响,于是今天就试着测试了一下. Python异常(谷歌开源风格指南) tip: 允许使用异常, 但必须小心. 定义: 异常是一种跳出代码块的正常控制流来处理错误或者其它异常条件的方式. 优点: 正常操作代码的控制流不会和错误处理代码混在一起. 当某种条件发生时, 它也允许控制流跳过多个框架

  • python编程的核心知识点总结

    一.为什么提出python编程的核心是什么? 我想要Python实现,这已经不是什么秘密了.WebAssembly它不仅会让Python进入浏览器,而且事实是两者都是IOS和安卓支持将JavaScript作为应用程序的一部分运行,它还可以让Python进入移动平台.这一切都让我兴奋. 但是当想到创建Python的新实现这一艰巨任务时,我的大脑也开始问到底是什么东西.是Python?我们一起生活过CPython长期以来,我怀疑我们大多数人只是认为"Python==CPython".皮皮试

  • Python编程functools模块中创建修改函数的高阶函数解析

    partial 函数 partial 为偏函数(有的地方也叫做部分应用函数),它是对函数的二次封装,将现有函数的部分参数提前绑定为指定值,然后再进行计算. 由于偏函数的可变参数少,因此函数调用的难度低. 直接展示代码: from functools import partial # 原函数声明 def show(name, level): print("name:", name, "level:", level) # 定义偏函数,封装 show() 函数,并为 na

  • Python编程functools模块创建修改的高阶函数解析

    目录 partial 函数 装饰器 @lru_cache reduce 函数 partial 函数 partial 为偏函数(有的地方也叫做部分应用函数),它是对函数的二次封装,将现有函数的部分参数提前绑定为指定值,然后再进行计算. 由于偏函数的可变参数少,因此函数调用的难度低. 直接展示代码: from functools import partial # 原函数声明 def show(name, level): print("name:", name, "level:&q

  • Python编程django实现同一个ip十分钟内只能注册一次

    很多小伙伴都会有这样的问题,说一个ip地址十分钟内之内注册一次,用来防止用户来重复注册带来不必要的麻烦 逻辑: 取ip,在数据库找ip是否存在,存在判断当前时间和ip上次访问时间之差,小于600不能注册,到登录界面,大于600可以注册,设计一个数据库来存储这个ip地址和访问时间, class Ip(models.Model): ip=models.CharField(max_length=20) time=models.DateTimeField() class Meta: verbose_na

  • python编程羊车门问题代码示例

    问题: 有3扇关闭的门,一扇门后面停着汽车,其余门后是山羊,只有主持人知道每扇门后面是什么.参赛者可以选择一扇门,在开启它之前,主持人会开启另外一扇门,露出门后的山羊,然后允许参赛者更换自己的选择. 请问: 1.按照你的第一感觉回答,你觉得不换选择能有更高的几率获得汽车,还是换选择能有更高的几率获得汽车?或几率没有发生变化? 答:第一感觉换与不换获奖几率没有发生变化. 2.请自己认真分析一下"不换选择能有更高的几率获得汽车,还是换选择能有更高的几率获得汽车?或几率没有发生变化?" 写出

  • Python编程实现的简单Web服务器示例

    本文实例讲述了Python编程实现的简单Web服务器.分享给大家供大家参考,具体如下: 最近有个需求,就是要创建一个简到要多简单就有多简单的web服务器,目的就是需要一个后台进程用来接收请求然后处理并返回结果,因此就想到了使用Python来实现. 首先创建一个myapp.py文件,其中定义了一个方法,所有的请求都会经过此方法,可以在此方法里处理传递的url和参数,并返回结果. def myapp(environ, start_response): status = '200 OK' header

  • Python编程实现输入某年某月某日计算出这一天是该年第几天的方法

    本文实例讲述了Python编程实现输入某年某月某日计算出这一天是该年第几天的方法.分享给大家供大家参考,具体如下: #基于 Python3 一种做法: def is_leap_year(year): # 判断闰年,是则返回True,否则返回False if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0: return True else: return False def function1(year, month, day): #

随机推荐