定义了两个函数装饰器。目标是检测一个函数是否应用了0、1或2个装饰器。
为什么下面的代码对第二个装饰器返回“False”?
def decorator1(f):
def wrapped(*args, **kwargs):
f(*args, **kwargs)
wrapped.dec1 = True
return wrapped
def decorator2(f):
def wrapped(*args, **kwargs):
f(*args, **kwargs)
wrapped.dec2 = True
return wrapped
@decorator1
@decorator2
def myfunc():
print(f"running myfunc")
if __name__ == "__main__":
myfunc()
print(f"myfunc has decorator1: {getattr(myfunc, 'dec1', False)}")
print(f"myfunc has decorator2: {getattr(myfunc, 'dec2', False)}")
字符串
测试结果:
running myfunc
myfunc has decorator1: True
myfunc has decorator2: False
型
我使用Python 3.9。
2条答案
按热度按时间gywdnpxw1#
实际上print语句中的这句话是不正确的:“myfunc has..."。不,
myfunc
既没有dec1
也没有dec2
。你调用装饰器返回的是一个新函数,而不是你传递的函数。我会解释的。此代码:
字符串
相当于:
型
请记住,您将这些动态属性添加到
wrapped
函数中。它们并不都适用于同一个myfunc
函数对象。它们适用于“their” Package 函数。 Package 函数是这两个装饰器中的两个不同对象:型
在堆叠装饰器之后,你可以期望
decorator1.<locals>.wrapped
有dec1
(因为它是外部的),但它没有dec2
。它在decorator2.<locals>.wrapped
上:型
如果你有这些类型的装饰器,你的假设就会起作用:
型
如何使用现有代码实现?
我不认为这是一个干净的方式,但它的工作,如果你想:
型
你看,通过while循环,我深入到内部找到原始的
myfunc
并将其添加到返回的 Package 函数中。我还将decX
属性添加到原始的myfunc
中。aoyhnmkz2#
与从每个装饰器添加单独的属性不同,您可以让装饰器协作并将它们的标记添加到共享属性(列表)中。
字符串