gpt4 book ai didi

Python 链接装饰器覆盖属性

转载 作者:太空宇宙 更新时间:2023-11-04 00:44:22 26 4
gpt4 key购买 nike

我有两个装饰器。每个装饰器都有一个函数作为参数。每个装饰器都会为函数设置一个属性。在单个函数上链接装饰器后,我希望看到 2 个新属性。但是,顶级装饰器 t2“覆盖”了 t1 设置的属性。否则,一切解决后t1不复存在。任何人都可以解释为什么以及如何解决它吗?

def t1(function):
def wrapper(*args, **kwargs):
setattr(wrapper, "t1", True)
return function(*args, **kwargs)
setattr(wrapper, "t1", False)
return wrapper

def t2(function):
def wrapper(*args, **kwargs):
setattr(wrapper, "t2", True)
return function(*args, **kwargs)
setattr(wrapper, "t2", False)
return wrapper

@t2
@t1
def test():
pass

最佳答案

它发生了,因为你的装饰器在包装器上设置了属性。当第一个装饰器在其包装器上设置属性时,它将包装器传递给第二个装饰器,第二个装饰器在第一个包装器之上添加另一个包装器并在第二个包装器上设置属性。所以你最终得到了第二个包装器。

In [3]: def decorator_a(fn):
...: def wrapper(*args, **kwargs):
...: return fn(*args, **kwargs)
...: print("I'm setting the attribute on function {}".format(id(wrapper)))
...: setattr(wrapper, "attr1", True)
...: return wrapper
...:

In [4]: def decorator_b(fn):
...: def wrapper(*args, **kwargs):
...: return fn(*args, **kwargs)
...: print("I'm setting the attribute on function {}".format(id(wrapper)))
...: setattr(wrapper, "attr2", True)
...: return wrapper
...:

In [5]: first_time_decorated = decorator_a(lambda x: x)
I'm setting the attribute on function 4361847536

In [6]: second_time_decorated = decorator_b(first_time_decorated)
I'm setting the attribute on function 4361441064

您可以通过在包装器上设置被装饰函数的所有属性来解决这个问题

In [14]: def decorator_a(fn):
...: def wrapper(*args, **kwargs):
...: return fn(*args, **kwargs)
...: setattr(wrapper, "attr1", True)
...: for attribute in set(dir(fn)) - set(dir(wrapper)):
...: setattr(wrapper, attribute, getattr(fn, attribute))
...: return wrapper
...:

In [15]: def decorator_b(fn):
...: def wrapper(*args, **kwargs):
...: return fn(*args, **kwargs)
...: setattr(wrapper, "attr2", True)
...: for attribute in set(dir(fn)) - set(dir(wrapper)):
...: setattr(wrapper, attribute, getattr(fn, attribute))
...: return wrapper
...:

In [16]: first_time_decorated = decorator_a(lambda x: x)

In [17]: second_time_decorated = decorator_b(first_time_decorated)

In [18]: second_time_decorated.attr1
Out[18]: True

In [19]: second_time_decorated.attr2
Out[19]: True

关于Python 链接装饰器覆盖属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40428156/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com