Python中不使用语法糖编写装饰器的方法及细节解析
不使用语法糖实现Python装饰器的精确方式
多层装饰器的无中间赋值等价实现
PEP318提到的func = dec2(dec1(func))并不是什么特殊的“无中间赋值”黑魔法,本质就是语法糖帮你完成了连续的函数调用嵌套+变量重赋值,完全不需要lambda或者修改函数名。
举个实际的例子:
语法糖写法:
def dec1(func): def wrapper(): print("执行dec1逻辑") func() return wrapper def dec2(func): def wrapper(): print("执行dec2逻辑") func() return wrapper @dec1 @dec2 def hello(): print("hello")
对应的非语法糖等价写法就是直接对原函数变量进行嵌套调用后的赋值:
def hello(): print("hello") hello = dec1(dec2(hello))
这里的执行逻辑是:先调用dec2(hello)得到一个包裹后的函数,再把这个结果作为参数传给dec1,最后把dec1返回的最终包裹函数重新赋值给hello变量——全程没有中间临时变量,但本质还是变量赋值,只是把嵌套调用的结果直接赋值给原变量而已。
property.setter的非语法糖正确实现
直接执行name = name.setter(name)会失效,核心原因是property.setter方法需要接收的是setter逻辑的函数,而不是已经创建好的property对象。正确的非语法糖实现需要分两步走:
先看语法糖版本:
class MyClass: def __init__(self): self._name = "" @property def name(self): return self._name @name.setter def name(self, value): self._name = value
对应的非语法糖写法拆解为:
class MyClass: def __init__(self): self._name = "" # 1. 先定义getter函数,创建初始的property对象(对应@property装饰器) def get_name(self): return self._name name = property(get_name) # 2. 定义setter函数,调用初始property对象的setter方法生成带setter的新property对象 def set_name(self, value): self._name = value name = name.setter(set_name)
这里的关键是:name.setter(set_name)会基于原有的property对象(只包含getter),生成一个新的包含setter逻辑的property对象,最后把这个新对象重新赋值给name变量,才能实现和语法糖一样的效果。
内容的提问来源于stack exchange,提问作者geckels1
相关产品推荐
相关产品推荐

