Python 中的函数与装饰器
函数
- 函数是一个对象
- 在定义函数的时候,实际上是定义了一个变量,在编译的时候,函数体会被编译成一个
code object
,保存到所定义的变量中 - 可以和变量赋值操作进行类比
装饰器
- 装饰器本质上是一个对象(可以是函数或者类),其接收一个对象(可以是函数或者类),然后返回一个新对象(可以是函数或者类)
- 返回的新对象内部调用了被装饰的对象,这样可以不改变原对象内部的代码而改变其功能
用法
-
最简用例
def decorator(func): def wrapper(*args, **kwargs): # some logic ... out = func(*args, **kwargs) # some logic ... return out #也可以是其他变量 return wrapper @decorator def function(arg): #some logic ... return output
- 加上装饰器的函数定义语句,相当于
function = decorator(function)
,它们编译时生成的字节码是一样的 - 语句
function(arg)
等价于decorator(func)(arg)
- 加上装饰器的函数定义语句,相当于
-
装饰器本身接受其他参数
- 此时的函数定义语句等价于
function = decorator(*args, **kwargs)(function)
- 此时加上
@decorator(*args, **kwargs)
后,语句function(arg)
等价于decorator(*args, **kwargs)(function)(arg)
- 相当于多加了一层嵌套函数
def outer_decorator(*args, **kwargs) def inner_decorator(func): def wrapper(*args, **kwargs): # some logic ... out = func(*args, **kwargs) # some logic ... return out #也可以是其他变量 return wrapper return inner_decorator @outer_decorator(*args, **kwargs) def function(arg): #some logic ... return output
- 此时的函数定义语句等价于
-
functools.wraps
装饰器- 用于装饰普通装饰器函数内部的
wrapper
函数 - 一般情况下,使用装饰器时,被装饰函数的一些元数据会被覆盖。例如,装饰后的函数的
__name__
和__doc__
会变成装饰器内部函数的名称和文档字符串,而不是原始函数的 functools.wraps
装饰器在编写装饰器时保留被装饰函数的元数据(metadata)
- 用于装饰普通装饰器函数内部的