Python Functools–update _ wrapper()
原文:https://www . geesforgeks . org/python-func tools-update _ wrapper/
Python 中的functiontools模块处理高阶函数,也就是对函数进行操作(作为参数)或返回函数以及其他此类可调用对象的函数。functools 模块提供了多种方法,如cached_property(func), cmp_to_key(func), lru_cache(func), wraps(func)
等。值得注意的是,这些方法以函数作为参数。
在本文中,我们将讨论 functools 模块提供的update_wrapper()
方法的目的和应用。此方法用于更新包装函数的元数据,以反映包装函数的元数据,从而提高代码的可读性和重用性。update_wrapper()
方法采用以下参数:
语法:@ functools . update _ WRAPPER(WRAPPER,wrapped,assigned = WRAPPER_ASSIGNMENTS,updated = WRAPPER_UPDATES)
参数:
- 包装器:一个包装器功能。
- 包装:被包装的功能或包装的功能。
- 赋值:包装函数的属性,作为元组赋给包装函数的匹配属性(可选参数)。
- 已更新:包装函数的属性,相对于作为元组的原始函数属性进行更新(可选参数)。
为了更好地理解这个方法,让我们观察几个在 Python 中使用装饰器和 partial的例子。
例 1:
# Defining the decorator
def hi(func):
def wrapper():
"Hi has taken over Hello Documentation"
print("Hi geeks")
func()
return wrapper
@hi
def hello():
"this is the documentation of Hello Function"
print("Hey Geeks")
# Driver Code
print(hello.__name__)
print(hello.__doc__)
help(hello)
输出:
wrapper
Hi has taken over Hello Documentation
Help on function wrapper in module __main__:
wrapper()
Hi has taken over Hello Documentation
在上例中,当我们使用装饰器函数 hi 并用它的包装器包装 hello 时,函数 hello 的模块级常量,如 name 、 doc 等。,被功能中包装的包装所取代。
使用 functools 模块中的分部时也会出现同样的情况。让我们看一个例子:
例 2:
import functools
def divide(a, b):
"Original Documentation of Divide"
return a / b
half = functools.partial(divide, b = 2)
oneThird = functools.partial(divide, b = 3)
try:
print(half.__name__)
except AttributeError:
print('No Name')
print(half.__doc__)
输出:
无名称 部分(func,args, *关键字)–部分应用给定参数和关键字 的新函数。
在上面的例子中,半和一三没有__name__
(引用时抛出属性错误),因为它们是通过分音创建的。作为它们的文档,它们继承了分部方法的文档。
由于模块级常量对于识别、管理和检索内容有着重要的作用,因此上述场景本身就存在问题。由于这些原因,元数据对于跟踪内容的使用非常重要。因此,如果一个人试图创建一个应用编程接口或库,它将不是用户友好的,因为帮助(函数)不会返回关于如何使用其方法的有意义的信息。帮助(函数)将返回包装函数的文档,这会让用户感到困惑。这个问题可以通过@functools.update_wrapper()轻松解决。
让我们考虑第一个例子。我们可以通过以下方式使用 update _ wrapper(): 示例 1:
# Python program to demonstrate
# ipdate)wrapper() method
import functools as ft
# Defining the decorator
def hi(func):
def wrapper():
"Hi has taken over Hello Documentation"
print("Hi geeks")
func()
# Note The following Steps Clearly
print("UPDATED WRAPPER DATA")
print(f'WRAPPER ASSIGNMENTS : {ft.WRAPPER_ASSIGNMENTS}')
print(f'UPDATES : {ft.WRAPPER_UPDATES}')
# Updating Metadata of wrapper
# using update_wrapper
ft.update_wrapper(wrapper, func)
return wrapper
@hi
def hello():
"this is the documentation of Hello Function"
print("Hey Geeks")
print(hello.__name__)
print(hello.__doc__)
help(hello)
输出:
更新的包装器数据 包装器分配:(“module”、“name”、“qualname”、“doc”、“ _ annotations _ ”) 更新:(“ _ dict _ ”) 你好 这是你好函数的文档 关于 module _ main _ _ 中函数你好的帮助:
hello() 这是 hello 函数的文档
通过使用 update_wrapper(),我们看到函数 hello 保留了其原始元数据。同样,让我们检查第二个示例,但是这次我们将使用 update_wrapper()
# Python program to demonstrate
# ipdate)wrapper() method
import functools
def divide(a, b):
"Original Documentation of Divide"
return a / b
half = functools.partial(divide,
b = 2)
oneThird = functools.partial(divide,
b = 3)
print("UPDATED WRAPPER DATA")
print(f'WRAPPER ASSIGNMENTS : {functools.WRAPPER_ASSIGNMENTS}')
print(f'UPDATES : {functools.WRAPPER_UPDATES}')
# Updating Metadata of wrapper
# using update_wrapper
ft.update_wrapper(half, divide)
try:
print(half.__name__)
except AttributeError:
print('No Name')
print(half.__doc__)
help(half)
help(oneThird)
输出:
更新的包装器数据 包装器分配:(“module”、“name”、“qualname”、“doc”、“ _ annotations _ ”) 更新:(“ _ dict _ ”) 分 分 原始文档关于模块中部分的帮助 main 对象:
divide = class partial(buildings . object) | partial(func,args, * keywords)–带有给定参数和关键字的 partial application |的新函数。 | |这里定义的方法: | | _ 调用 __(self,/,args,kwargs) |调用 self 作为函数。 | | delattr(self,name,/) |实现 delattr(self,name)。 | | _ getattribute _ (self,name,/) | Return getattr(self,name)。 | | new(args,**kwargs)从内置中。键入 |创建并返回一个新对象。请参阅帮助(类型)以获得准确的签名。 | | _ 减少 _ (……) |泡菜帮手 | | __repr__(自我,/) |归还 repr(自我)。 | | __setattr__(self,name,value,/) |实现 setattr(self,name,value)。 | | _ setstate _ (……) | |————————————————— |此处定义的数据描述符: | | _ dict _ _ | | args |未来部分调用的参数元组 | | func |未来部分调用中要使用的函数对象
部分对象的帮助:
类 partial(building ins . object) | partial(func,args, * keywords)–带有给定参数和关键字的 partial application |的新函数。 | |这里定义的方法: | | _ 调用 __(self,/,args,kwargs) |调用 self 作为函数。 | | delattr(self,name,/) |实现 delattr(self,name)。 | | _ getattribute _ (self,name,/) | Return getattr(self,name)。 | | new(args,**kwargs)从内置中。键入 |创建并返回一个新对象。请参阅帮助(类型)以获得准确的签名。 | | _ 减少 _ (……) |泡菜帮手 | | __repr__(自我,/) |归还 repr(自我)。 | | __setattr__(self,name,value,/) |实现 setattr(self,name,value)。 | | _ setstate _ (……) | |————————————————— |此处定义的数据描述符: | | _ dict _ _ | | args |未来部分调用的参数元组 | | func |未来部分调用中要使用的函数对象
在这个例子中,我们看到一半继承了函数除的基本模块级常数。当我们使用 help(半)时,我们看到它部分来自 divide。值得注意的是,oneThird 的情况并非如此,因为 help(oneThird)不会告诉我们父函数。
因此,通过上面的插图,我们可以理解 functools 模块中提供的 update_wrapper(…)方法的用例。为了保留函数的元数据以备将来使用,update_wrapper(…)是一个功能强大的工具,使用起来没有太多麻烦。因此,该方法在装饰者和分支的情况下非常有用。
版权属于:月萌API www.moonapi.com,转载请注明出处