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