python-3.x 如何调用'functools.update_wrapper'的例子有哪些?

ozxc1zmp  于 2023-03-13  发布在  Python
关注(0)|答案(1)|浏览(127)

the python website上有一些关于functools.wraps的文档
然而,我在看一些例子时遇到了麻烦。关于如何在不使用functools.wraps作为装饰器的情况下调用functools.wrap,有哪三个用例(例子)?
优选地,存在至少一个尽可能简单的示例和至少一个非常复杂的示例。
这个复杂的示例不会使用函数参数的任何默认参数。

functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

这里有一些文档,但没有任何示例或使用情形

更新 Package 函数,使其看起来与 Package 函数相同。可选参数是元组,用于指定将原始函数的哪些属性直接分配给 Package 函数上的匹配属性,以及使用原始函数中的相应属性更新 Package 函数的哪些属性。这些参数的默认值是模块级常量WRAPPER_ASSIGNMENTS(其将文档串分配给 Package 函数的__module____name____qualname____annotations____doc__)和WRAPPER_UPDATES(其更新 Package 函数的dict,即示例字典)。
为了允许出于内省和其他目的访问原始函数(例如,绕过缓存装饰器,如lru_cache()),此函数自动向 Package 器添加一个__wrapped__属性,该属性引用正在 Package 的函数。
这个函数的主要用途是在装饰器函数中 Package 装饰后的函数并返回 Package 器。如果 Package 器函数没有更新,返回函数的元数据将反映 Package 器定义而不是原始函数定义,这通常是没有帮助的。
update_wrapper()可以与函数以外的可调用对象一起使用。忽略在assigned或updated中命名的任何属性,这些属性在被 Package 的对象中缺失(即,此函数不会尝试在 Package 函数上设置它们)。如果 Package 函数本身缺失在updated中命名的任何属性,仍会引发AttributeError。

ccrfmcuu

ccrfmcuu1#

文档是直接的-他们可能会感到困惑,由于术语“ Package 器”和“ Package ”-但一旦一个人阅读它的注意,并没有混淆这些,他们是明确的。
“复杂的描述”实际上只是讨论了被分配或更新的默认属性--很少需要更改这些属性--除非有真正的用例:在这一点上,参数中应该写什么在文档中是清楚的。也许你会因为它默认复制的函数属性而感到困惑?这些是语言在函数中使用的属性,由于语言本身在其他地方的定义,它们是有意义的。此外,如果一个新的函数属性出现,并且开始有意义地将其复制到 Package 器中,这些默认值很可能会被更新--这就是Python 3.2中开始复制__annotations__时发生的事情。例如(就像文档中一样,就在你引用的部分下面)
这个函数本身处理了很多极端情况(比如,感谢开发人员,Python的很多stdlib函数都是这样做的)--而且没有必要为它的复杂用例编写示例。
几乎在任何时候,我们都会使用@wraps而不是update wrapper,后者有合理的默认值--并且在中级Python程序员中或多或少是众所周知的。
为了说明默认设置是多么合理:尽管函数命名空间中的额外属性已经很少了,但是它们 * 确实存在 * 于某些地方--并且......默认情况下更新 Package 器__dict__的策略将 * 简单地 * 为这些属性开箱即用。
例如,typing模块有几个函数定义了一个__mro_entries__-它是一个非标准的函数属性,允许一个函数在类定义中作为基类使用。如果使用默认版本的.update_wrapper来修饰其中的一个,它仍然可以工作,不需要改变默认值:

In [49]: import typing, functools

In [50]: def decorator(func):
    ...:     # example decorator
    ...:     def wrapper(*args, **kw):
    ...:         print(func.__name__)
    ...:         return func(*args, **kw)
    ...:     wrapper = functools.update_wrapper(wrapper, func)
    ...:     return wrapper
    ...: 

In [51]: new_ntuple = decorator(typing.NamedTuple)

In [52]: new_ntuple.__mro_entries__
Out[52]: <function typing._namedtuple_mro_entries(bases)>

啊-文档遗漏的一件事是,它没有明确说明assignedupdated的两个默认参数是 * string * 的元组,而不是任何其他对象的元组。但是,正如我上面所说,一旦有人达到了他们需要定制这个调用的地步,最多在编写代码的时候,它们必须是字符串,这一点就会变得很明显。因为别的都说不通。

相关问题