gpt4 book ai didi

python - functools.wraps的 `assigned`和 `updated`参数如何使用?

转载 作者:太空狗 更新时间:2023-10-29 21:54:58 25 4
gpt4 key购买 nike

我知道包装有如下属性:

functools.wraps(wrapped[, assigned][, updated])

但我想知道如何使用 assignedupdated 参数,有人有例子吗?

最佳答案

“已分配”参数告诉包装函数上的哪些属性将分配给包装(装饰)函数上的同名属性。默认情况下,它们是 '__module__'、'__name__'、'__doc__',它们在变量 functools.WRAPPER_ASSIGNMENTS 中被定义为默认值。正如@abarnet 在评论中所说,另一个可能想要复制的属性示例是 Python 3.x 中的函数注释 - 因此您可能希望分配的参数为:('__module__', '__name__ ', '__doc__', '__annotations__') .

“更新”参数或多或少是相同的,但是包装器中的相应属性将使用装饰函数中的该属性调用它的“更新”方法 - 这意味着它仅在两个属性都是可变的时才有效映射 - 例如字典。默认情况下,它将使用包装的 __dict__ 更新包装器的 __dict__ 属性,使包装器函数反射(reflect)它可能已由不同的底层装饰器分配的所有无关属性(在调用“包装”的装饰器之前应用的装饰器被应用)。更改“已更新”的唯一可能用例是将其更改为空序列,以防止 __dict__ 被更新。否则,如果您想更新更多属性,那将意味着您将从事一个项目,该项目将在可调用对象上使用不同的字典属性,此时您肯定会遇到比不知道如何正确使用“包装”更多的问题.

TL;DR:您可能发现一些有用的东西:

@wraps(func, ('__module__', '__name__', '__doc__', '__anotations__'), ())
def wrapper(*args, **kw):
...

但不一定。

作为最后的轶事说明,如果装饰对象是具有 __call__ 方法而不是函数的类的实例,则 __dict__ 更新将使包装函数拥有装饰实例的所有实例属性的副本——这更多是副作用而不是有用的东西,因为这些复制的属性不会跟随装饰实例中状态的进一步变化(并且装饰实例上的方法仍然会接收“self”作为未包装的实例):

>>> from functools import wraps
>>> class MyCallable(object):
... def pr(self):
... print(self.a)
... def __call__(self, new_a):
... self.a = new_a


>>> def deco(clb):
... @wraps(clb)
... def wrapper(*args):
... return clb(*args)
... return wrapper
...
>>> m = MyCallable()
>>> m(1)
>>> m.a
1
>>> m.pr()
1
>>> m = deco(m)
>>> m(2)
>>> m.a
1
>>> m.__wrapped__.pr()
2

因此,这可能是您不想将 __dict__ 复制到包装器,而是始终通过 __wrapped__ 属性访问原始实例的示例,如上所示。但是,我实际上离题了,因为我从来没有见过有人用装饰器包装类的实例,并且想不出这样的用例,如果类方法首先做装饰器应该做的事情,就不能更好地解决这个问题。

关于python - functools.wraps的 `assigned`和 `updated`参数如何使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29933914/

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