装饰器是一种特殊类型的函数,可以修改其他函数的功能或行为。它们通常用于扩展或改变已有函数的行为而不必修改其源代码。
装饰器的基本概念
装饰器本质上是一个接受函数作为参数的函数,返回一个新函数。使用@function
形式的语法糖来调用装饰器函数。
装饰器的工作原理
当一个函数被定义时,它不会立即执行。定义后,可以通过装饰器进行包装。装饰器接收这个函数作为参数,并返回一个新的函数。这个新的函数可以对原函数进行增强、修改或包装,然后再返回这个新函数。
-- -------------------- ---- ------- --- ------------------- --- ---------- ---------------- -- --------- ------ --- -------- -- --------- ------ ---------------- -- --------- ----- --- -------- -- --------- ------ ------- ------------- --- ------------ --------------- -----------
在这个例子中,say_hello
函数被 my_decorator
装饰器所装饰。当调用 say_hello()
时,实际上是调用了 my_decorator(say_hello)
返回的新函数 wrapper
。
使用带参数的装饰器
有时候需要传递参数给装饰器,这可以通过嵌套函数实现。
参数化装饰器
参数化装饰器允许你在定义装饰器时传递额外的参数。这些参数可以用来控制装饰器的行为。
-- -------------------- ---- ------- --- ------------------ --- ----------------------- --- -------------- ---------- --- - -- ----------------- ------ - ----------- --------- ------ ------ ------ ------- ------ ---------------- -------------------- --- ------------ ------------- --------- --------------
在这个例子中,repeat
是一个参数化的装饰器,它接受一个参数 num_times
来指定函数需要重复执行的次数。通过在装饰器上指定参数 @repeat(num_times=3)
,我们告诉装饰器 greet
函数应该重复执行三次。
类装饰器
类装饰器与函数装饰器类似,但它们接收的是类而不是函数。类装饰器通常用于修改类的属性或方法。
使用类作为装饰器
类装饰器可以用来添加新的方法或修改类的方法和属性。
-- -------------------- ---- ------- ----- ---------- --- -------------- ------ --------- - ---- --- -------------- ------ ---------- -------------- --------- ---------- ------ ---------------- --------- ---------- --- ---------- ------------- ------- ---------- ---------
在这个例子中,Decorator
类被用作装饰器。当 example
函数被调用时,实际上会调用 Decorator
类的 __call__
方法。
带有状态的装饰器
有时我们需要装饰器能够记住一些状态信息。这可以通过在装饰器内部创建闭包来实现。
记忆装饰器
记忆装饰器可以用来缓存函数的结果,以便在未来相同的输入下快速返回结果。
-- -------------------- ---- ------- ---- --------- ------ ----- --- ------------ ------------- - -- ------------ --- --------------- -- ---- --- -- -------------- ------------------- - ----------- ------ ------------------- ------ ------- ------ --- ------------- -- - - -- ------ - ----- ------ -------------- - -------------- --------------------
在这个例子中,cache
装饰器通过字典 cached_values
来存储已经计算过的值,从而避免了重复计算。
装饰器堆叠
可以将多个装饰器应用于同一个函数。装饰器从内到外依次应用,也就是说,最靠近函数定义的装饰器首先被执行。
多重装饰器
多重装饰器允许你组合不同的功能。
-- -------------------- ---- ------- --- ---------------- --- ---------- ------ ----- - ------ - ------ ------ ------- --- ------------------ --- ---------- ------ ----- - ------ - ------ ------ ------- ---------- ------------ --- ------ ------ -------- ------------
在这个例子中,say
函数首先被 make_italic
装饰器处理,然后结果又被 make_bold
装饰器处理。
内置装饰器
Python 提供了一些内置的装饰器,如 @staticmethod
, @classmethod
, 和 @property
。
静态方法和类方法
静态方法和类方法是特殊的装饰器,用于定义不依赖于实例或类的特定行为。
-- -------------------- ---- ------- ----- -------- ------------- --- ---------------- ------------- ------ --- ---- --------- ------------ --- ------------------ ------------ ------ --- ---- --------- ----------------------- ----------------------
在这个例子中,static_method
不需要任何实例或类作为参数,而 class_method
接受类本身作为第一个参数。
属性装饰器
属性装饰器允许你像访问普通属性一样访问类中的方法。
-- -------------------- ---- ------- ----- -------- --- --------------- ----------- - - --------- --- ------------ ------ ----------- ------------- --- ----------- ----------- -- --------- -- -- ----------- - --------- --- - --------- ---------------- --------- - -- ----------------
在这个例子中,value
属性通过 @property
装饰器被定义为只读属性,而通过 @value.setter
可以设置属性的值。
总结
装饰器是 Python 中非常强大的工具,可以让你以简洁的方式扩展或修改函数或类的行为。通过理解装饰器的工作原理和如何使用它们,你可以编写出更灵活、可维护的代码。