其它内容推荐:免费使用,阿里开源3D人体重建模型,单张图片指定动作生成视频
装饰器(Decorator)
装饰器本质上是一个函数,它接收一个可调用对象作为参数,并返回一个可调用对象。目的是不修改原函数代码的情况下,动态地扩展函数的功能。
可调用对象Callable Object,即可以通过 ()
操作符调用的对象,比如函数(Python中一切皆对象,函数本身也是对象,Python为其隐式实现了__call__
,所以能被调用)、实现了__call__
方法的类对象以及类本身(类的实例化过程本质上是一个函数调用,即调用初始化函数__init__
)等等。可以用内建函数callable()
验证是不是可调用对象。
基础装饰器
装饰器的定义是只能接收一个可调用对象(一般是函数,下文中都称作函数)作为参数,返回一个可调用对象;
装饰器返回的那个函数一般习惯定义在装饰器内部(Python中的函数可以定义在函数内部),内部函数(也称闭包)可以访问外部函数的变量,这使得装饰器能够保存状态。
def my_decorator(func):
def wrapper1():
func()#实际上这个函数用不用都行。只要装饰器符合接收一个函数并返回一个函数的定义就行
return wrapper
@my_decorator
def say_hello1():
print("Hello 1!")
say_hello1()#实际上相当于调用wrapper1()
解释:
-
my_decorator
是一个装饰器函数,它接受一个函数func
作为参数。 -
wrapper
是一个内部函数,它在调用func
之前和之后执行一些额外的代码。 -
@my_decorator
是装饰器的语法糖,它等价于say_hello1 = my_decorator(say_hello1)
。 -
调用
say_hello1()
时,实际上调用的是wrapper1()
函数。
高级装饰器,可带参数
装饰器也可以接受其它参数,这使得装饰器更加灵活。如果装饰器需要接受其它参数(上面提到装饰器只能接收一个可调用对象作为参数),可以再嵌套一层函数。这种设计使得装饰器可以非常灵活地接受额外的参数,同时保持了 Python 装饰器的简洁性和一致性。
def repeat(num_times):
def decorator(func):
def wrapper2(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper2
return decorator
@repeat(num_times=3)
def say_hello2():
print("Hello 2!")
#等同于say_hello2 = repeat(3)(say_hello2)
解释:
-
repeat
是一个装饰器工厂函数,它接收一个参数num_times
,返回装饰器函数decorator。装饰器工厂函数可以接收任意个数的参数,使用时,必须通过带括号的方式来调用工厂函数,即使括号中没有参数。 -
decorator
是实际的装饰器函数(相当于6.1中的基础装饰器),它接收一个可调用对象func
作为参数,返回wrapper2
。 -
所以当我们调用
say_hello2()
时,实际上是调用wrapper2()
,即等同于say_hello2 = repeat(3)(say_hello2)