欢迎光临散文网 会员登陆 & 注册

Python内置装饰器太强了

2023-03-29 14:54 作者:啥都会一点的研究生  | 我要投稿

装饰器可以在编写更少、更简单代码的基础上实现复杂的逻辑,并在任何地方都能调用

是体现“Python 之禅”的最佳Python特性

有许多很棒的内置Python装饰器使得效率蹭蹭上涨,只需使用一行代码就可以为现有函数或类添加复杂的功能

一起来看看吧!

1.@lru_cache:通过缓存加速程序

使用缓存技巧加速 Python 函数的最简单方法是使用@lru_cache装饰器

这个装饰器可以用来缓存一个函数的结果,这样后续调用相同参数的函数就不会再执行了

它对于计算量大或使用相同参数频繁调用的函数特别有用

看一个直观的例子:

该例是经典的计算斐波那契数

计算fibonacci(30)的时候很耗时,很多前面的Fibonacci数在递归过程中会重复计算多次

现在,使用@lru_cache装饰器来加速它:

如上所示,使用@lru_cache装饰器后,可以在0.00002990秒内得到相同的结果,比之前的0.18129450秒快了很多

@lru_cache装饰器有一个maxsize参数,指定存储在缓存中的最大结果数

当缓存已满并且需要存储新结果时,最近最久未使用的结果将从缓存中弹出

这称为最近最久未使用 (Least Recently Used,LRU) 策略

默认情况下,maxsize设置为128

如果将其设置为None,如示例,LRU 功能将被禁用,并且缓存可以无限增长

2. @total_ordering:类装饰器,填充缺失的比较方法

来自functools模块的@total_ordering装饰器,用于根据定义的方法为Python类生成缺少的比较方法

例如:

如上所示,在Student类中没有定义__ge____gt__  __le__ 方法

但是,@total_ordering的存在,让我们在不同实例之间的比较结果都是正确的,优点显而易见

  • 可以使代码更清晰并节省时间,因为不需要写所有的比较方法

  • 一些旧类可能没有定义足够的比较方法,@total_ordering装饰器确保使用安全

3. @contextmanager:制作定制的上下文管理器

Python提供上下文管理器机制来帮助正确的管理资源

大多数情况下,我们都知道使用with语句:

如上,使用with语句打开一个文件,写入后自动关闭

不需要显式的调用f.close()函数来关闭文件

有时,需要为一些特殊的需求定义一个自定义的上下文管理器

在这种情况下,@contextmanager装饰器该登场了

例如,下面的代码实现了一个简单的自定义上下文管理器,可以在文件打开或关闭时打印相应的信息

4. @property:为Python类设置getter和setter

getter和setter是面向对象编程(OOP)中的重要概念

对于类的每个实例变量,getter方法返回它的值,而setter方法设置或更新它的值

鉴于此,getter和setter也分别称为访问器和修改器

二者用于保护数据不被直接和意外地访问或修改

不同的OOP语言有不同的机制来定义getter和setter

在Python中,可以简单地使用@property装饰器

如上所示,score变量不能设置为 999,这是一个无意义的数字

因为使用@property装饰器在setter函数中限制了它的可接受范围

5. @cached_property:将方法的结果缓存为属性

Python3.8为functool模块引入了一个新的强大装饰器——@cached_property

可以将一个类的方法转换为一个属性,该属性的值计算一次,然后在实例的生命周期内作为普通属性缓存

在上面的代码中,通过@cached_property修饰了area方法

所以没有对同一个不变实例的circle.area进行重复计算

6. @classmethod:在Python类中定义类方法

在Python类中,有3种可能的方法类型:

  • 实例方法:绑定到实例的方法。可以访问和修改实例数据。在类的实例上调用实例方法,可以通过self参数访问实例数据

  • 类方法:绑定到类的方法。不能修改实例数据。在类本身上调用类方法,接收类作为第一个参数,通常命名为cls

  • 静态方法:未绑定到实例或类的方法

实例方法可以定义为普通的Python函数,只要第一个参数是self

但是,要定义一个类方法,需要使用@classmethod装饰器

为了演示,以下示例定义了一个类方法,可用于通过radius获取Circle实例:

7. @staticmethod:在Python类中定义静态方法

如前所述,静态方法不绑定到实例或类

被包含在一个类中只是因为在逻辑上属于那个类

静态方法通常用于执行一组相关任务(例如数学计算)的实用程序类中

通过将相关函数组织到类中的静态方法中,代码将变得更有条理且更易于理解

要定义一个静态方法,只需要使用@staticmethod装饰器

看一个例子:

8. @dataclass:用更少的代码定义特殊类

@dataclass装饰器(Python 3.7引入)可以自动为一个类生成几个特殊的方法,如__init____repr____eq____lt__

因此,可以节省大量编写这些基本方法的时间

如果一个类主要用于存储数据,那么@dataclass装饰器是最需要被考虑的

下面的示例只定义了一个名为Point的类的两个数据字段

9. @atexit.register:注册一个在程序正常终止时执行的函数

来自atexit模块的@register装饰器可以在Python解释器退出时执行一个函数

这个装饰器对于执行最终任务非常有用,例如释放资源

例如:

输出是:

如示例所示,由于使用@register装饰器,终端打印了“Bye bye!”

即使没有显式调用goodbye函数


Python内置装饰器太强了的评论 (共 条)

分享到微博请遵守国家法律