🐍Python 函数与面向对象
装饰器与闭包
面试回答
常见问法
Python 装饰器的本质是什么?它和闭包是什么关系?
回答
装饰器本质上是“接收一个函数,返回一个新函数”的高阶函数写法;闭包则是内部函数引用了外部函数作用域中的变量,并在外部函数返回后仍然保留这些变量。
装饰器之所以常和闭包一起出现,是因为很多装饰器都靠闭包保存被装饰函数和附加状态。
def log_decorator(func):
def wrapper(*args, **kwargs):
print("before")
result = func(*args, **kwargs)
print("after")
return result
return wrapper
追问
@decorator为什么只是语法糖- 为什么要用
functools.wraps - 带参数装饰器为什么要多包一层
原理展开
@decorator 等价于:
def hello():
print("hello")
hello = log_decorator(hello)
带参数装饰器通常是三层:
from functools import wraps
def repeat(n):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
这里:
- 最外层收装饰器参数
- 中间层收函数对象
- 最内层是真正执行时的包装逻辑
易错点
- 只会写
@语法,不会展开本质 - 忘记
wraps导致函数名、文档字符串丢失 - 把闭包和普通嵌套函数混为一谈