推荐8个炫酷的 Python 装饰器!

Python 编程语言的一大优点是它把所有功能都打包到一个小包中,这些功能非常有用。许多特性可以完全改变 Python 代码的功能,这使得该语言更加灵活。如果使用得当,其中一些功能可以有效缩短编写程序所需的时间。实现这些目标的一个很好的例子是 Python 的装饰器

装饰器(decorators)是一个可以用于改变一个Python函数对象行为的函数。它们可以应用于类和函数,可以做很多非常有趣的事情!装饰器可以用来缩短代码、加速代码并彻底改变代码在 Python 中的行为方式。不用说,这当然可以派上用场!今天我想炫耀一些我认为值得一试的装饰器。有很多装饰器,但我选择了一些我认为具有最酷功能的装饰器。

1. @lru_cache

此列表中的第一个装饰器来自 functools 模块。该模块包含在标准库中,非常易于使用。它还包含比这个装饰器更酷的功能,但这个装饰器肯定是我最喜欢的。此装饰器可用于使用缓存加速函数的连续运行。当然,这应该在使用时记住一些关于缓存的注意事项,但在通用使用情况下,大多数时候这个装饰器是值得使用的。

能够用一个简单的装饰器来加速代码是非常棒的。可以从这样的装饰器中受益的函数的一个很好的例子是递归函数,例如计算阶乘的函数:

def factorial(n): return n * factorial(n-1) if n else 1

递归在计算时间上可能非常困难,但添加此装饰器有助于显着加快此函数的连续运行速度。

@lru_cachedef factorial(n):     return n * factorial(n-1) if n else 1

现在每当我们运行这个函数时,前几个阶乘计算将被保存到缓存中。因此,下次我们调用该函数时,我们只需要计算我们之前使用的阶乘之后的阶乘。当然,并不是所有的阶乘计算都会被保存,但是很容易理解为什么这个装饰器的一个很好的应用程序来加速一些自然很慢的代码。

2. @jit

JIT 是即时编译(Just In Time)的缩写。通常每当我们在 Python 中运行一些代码时,发生的第一件事就是编译。这种编译会产生一些开销,因为类型被分配了内存,并存储为未分配但已命名的别名。使用即时编译,我们在执行时才进行编译。在很多方面,我们可以将其视为类似于并行计算的东西,其中 Python 解释器同时处理两件事以节省一些时间。

Numba JIT 编译器因将这一概念提供到 Python 中而闻名。与@lru_cache 类似,可以非常轻松地调用此装饰器,并立即提高代码的性能。Numba 包提供了 jit 装饰器,它使运行更密集的软件变得更加容易,而不必进入 C。

以下案例使用@jit装饰器加速蒙特卡洛方法计算。

from numba import jitimport random
@jit(nopython=True)def monte_carlo_pi(nsamples): acc = 0 for i in range(nsamples): x = random.random() y = random.random() if (x ** 2 + y ** 2) < 1.0: acc += 1 return 4.0 * acc / nsamples

3. @do_twice

do_twice 装饰器的功能与它的名字差不多。此装饰器可用于通过一次调用运行两次函数。这当然有一些用途,我发现它对调试特别有用。它可以用于测量两个不同迭代的性能。以 Functools 为例,我们可以让一个函数运行两次,以检查是否有改进。该函数由 Python 中的装饰器模块提供,该模块位于标准库中。

from decorators import do_twice@do_twicedef timerfunc():    %timeit factorial(15)

4. @count_calls

count_calls 装饰器可用于提供有关函数在软件中使用多少次的信息。像 do_twice 一样,这当然可以在调试时派上用场。当添加到给定的函数时,我们将收到一个输出,告诉我们该函数每次运行时已经运行了多少次。这个装饰器也在标准库的装饰器模块中。

from decorators import count_calls@count_callsdef function_example():    print('Hello World!')    function_example()function_example()function_example()

5. @dataclass

为了节省编写类的时间,我一直使用的最好的装饰器之一是@dataclass装饰器。这个装饰器可用于快速编写类中常见的标准方法,这些方法通常会在我们编写的类中找到。

这个装饰器来自 dataclass 模块。这个模块也在标准库中,所以不需要PIP来尝试这个例子!

from dataclasses import dataclass@dataclassclass Food:    name: str    unit_price: float    stock: int = 0    def stock_value(self) -> float:        return(self.stock * self.unit_price)

这段代码将自动创建一个初始化函数 __init__(),其中包含填充类中数据所需的位置参数。它们也将自动提供给 self,因此无需编写一个很长的函数来将一些数据参数放入类中。

6. @singleton

为了理解单例装饰器的用途,我们首先需要了解单例(singleton)是什么。从某种意义上说,单例是全局变量类型的一个版本。这意味着类型被定义为只存在一次。尽管这些在 C++ 等语言中很常见,但在 Python 中却很少见到。使用单例,我们可以创建一个只使用一次的类并改变类,而不是通过初始化来构造新的类型。

通常,单例装饰器是由用户自己编写的,实际上并不是导入的。这是因为单例仍然是对我们单例装饰器中提供的模板的引用。我们可以命名一个单例函数并编写一个包装器,以便在我们的类上使用这个装饰器:

def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper
@singletonclass cls: def func(self):

解决此问题的另一种方法是使用元类。

7. @use_unit

在科学计算中经常派上用场的一种装饰器是 @use_unit 装饰器。此装饰器可用于更改返回结果的表示单位。这对于那些不想在数据中添加度量单位但仍希望人们知道这些单位是什么的人很有用。这个装饰器也不是在任何模块中真正可用,但它是非常常见的,对科学应用程序非常有用。

def use_unit(unit):    '''Have a function return a Quantity with given unit'''    use_unit.ureg = pint.UnitRegistry()    def decorator_use_unit(func):        @functools.wraps(func)        def wrapper_use_unit(*args, **kwargs):            value = func(*args, **kwargs)            return value * use_unit.ureg(unit)        return wrapper_use_unit    return decorator_use_unit@use_unit('meters per second')def average_speed(distance, duration):    return distance / duration

8. @singledispatch

Functools 凭借非常有用的@singledispatch 装饰器再次在此列表中脱颖而出。单调度是一种编程技术,在许多编程语言中都很常见,因为它是一种非常棒的编程方式。虽然我更喜欢多调度,但我认为单调度可以在很多方面扮演相同的角色。

这个装饰器使得在 Python 中使用多类型数据变得更加容易, 尤其当我们希望通过同一方法传递多种类型数据时,情况更是如此。我在我的 FuncTools 文章中写了更多关于这个的内容,所以如果你对使用单一调度方法感兴趣,我推荐它。

@singledispatchdef fun(arg, verbose=False): if verbose: print('Let me just say,', end=' ') print(arg)
@fun.registerdef _(arg: int, verbose=False): if verbose: print('Strength in numbers, eh?', end=' ') print(arg)
@fun.registerdef _(arg: list, verbose=False): if verbose: print('Enumerate this:') for i, elem in enumerate(arg): print(i, elem)

文章来源:https://towardsdatascience.com/10-fabulous-python-decorators-ab674a732871

(0)

相关推荐

  • Numba是什么?如何使用?

    Numba,一款可以让Python函数编译为机器代码的JIT编译器,它可以加速Python运行,想必很多人对它都十分感兴趣,接下来我们就来看看吧. Numba是什么? Numba是一个库,可以在运行时 ...

  • 初识装饰器函数

    我之前看装饰器文章介绍,很少有用 装饰器函数这种称谓的.但是今天大邓简单的学了下装饰器,觉得应该先让大家知道装饰器是一种函数,让大家从熟悉的函数去学习装饰器.大邓姑且草率的将其称呼为 装饰器函数 装饰 ...

  • 第20天:Python 之装饰器

    第20天:Python 之装饰器

  • 【编程课堂】装饰器浅析

    Python 拥有丰富强大的功能和表达特性,其中之一便是装饰器,装饰器能够在不改变函数.方法.类本身的情况下丰富他们的功能. 比如,我们有一个函数 func ,我们希望在不改变函数的前提下记录函数运行 ...

  • 【强烈推荐】一个炫酷的博客网站

    一.前言 这不,前两天有位网友与我讨论问题,有些有更好的解答,但是推文已经发出去了.我这边已经有改过来了,但是没办法实时更新到公众号上去. 所以,小编建了一个个人博客来解决这个问题.博客网站有很多,像 ...

  • 浅析Python装饰器

    浅析Python装饰器

  • 【进阶】一文读懂Python装饰器,搞清来龙去脉!

    (给机器学习算法与Python学习加星标,提升AI技能) 选自pouannes.github.io 作者:Pierre Ouannes 本文由机器之心(nearhuman2014)翻译 原文:http ...

  • 炫酷的音乐播放器来了,让你的音乐更加火爆

    近期在抖音,快手上火爆的 3D炫酷音乐播放器的教学来了 看教程之前 先来看一下效果视频 小编推荐:一定要带耳机观看 小编推荐:一定要带耳机观看 小编推荐:一定要带耳机观看 效果视频

  • 说说对于Python装饰器的理解?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  • 人人都能看懂的 Python 装饰器入门教程!

    很多人认为理解了装饰器的概念和用法后,会觉得自己的 Python 水平有一个明显的提高. 但很多教程在一上来就会给出装饰器的定义以及基本用法,例如你一定会在很多文章中看到例如代码运行时间计时器等相关常 ...

  • Python|装饰器

    一对象的概念python的所有内容都可以作为对象,这意味着这些内容可以作为参数作用于其他的"对象",这不难理解,就像在函数中,可以把另一个函数作为参数,甚至是类作为参数,,因此经常 ...

  • 一文搞懂Python装饰器

    一.前言 本不打算专门写文来讲装饰器的,但有不少粉丝问到了,自己查阅了一些网上的装饰器教程,发现讲的通俗易懂的不多,也有不少照搬的文章.所以我这里专门来讲一讲它. 个人在用的人工智能学习网站推荐给大家 ...

  • 推荐一个免费作图APP:20多万个图片、视频模板,一键做出炫酷设计!

    助友们好,我是助攻姐.   之前我给大家推荐过很多设计类 UP 主,纪录片和设计网站,反响都还不错.   但也有助友来问我,那些网站需要一定的门槛,有没有适合新手的设计软件推荐?   一句话,助友的需 ...