Python中的functools模塊處理高階函數,即在(作為參數)上操作或返回函數以及其他此類可調用對象的函數。 functools模塊提供了多種方法,例如cached_property(func), cmp_to_key(func), lru_cache(func), wraps(func)
等等。值得注意的是,這些方法將函數作為參數。
在本文中,我們將討論該工具的目的和應用。update_wrapper()
functools模塊提供的方法。此方法用於更新包裝函數的元數據,以反映包裝函數的元數據,從而提高可讀性和re-usability代碼。這update_wrapper()
方法采用以下參數:
用法:@functools.update_wrapper(wrapper, wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES)
參數:
- wrapper:包裝函數。
- wrapped:被包裝的函數或被包裝的函數。
- assigned:包裝函數的屬性以元組(可選參數)的形式分配給包裝函數的匹配屬性。
- updated:包裝函數的屬性相對於原始函數屬性(作為元組(可選參數))進行了更新。
為了更好地理解此方法,讓我們觀察一下在Python中使用裝飾器和局部函數的幾種情況。
範例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__等)將替換為函數hi中的包裝器。
當使用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__)
輸出:
No Name
partial(func, *args, **keywords) - new function with partial application
of the given arguments and keywords.
在上麵的示例中,Half和oneThird沒有__name__
(在引用時拋出AttributeError),因為它們是通過局部函數創建的。作為他們的文檔,他們繼承了partial方法的文檔。
上麵的情況從本質上來說是有問題的,因為模塊級常量用於標識,管理和檢索內容的重要目的。由於這些原因以及跟蹤內容的使用情況,元數據非常重要。因此,如果嘗試創建一個API或庫,它將不是user-friendly,因為help(function)不會返回有關如何使用其方法的有意義的信息。幫助(函數)將返回包裝函數的文檔,這會使用戶感到困惑。通過@ 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)
輸出:
UPDATED WRAPPER DATA
WRAPPER ASSIGNMENTS:(‘__module__’, ‘__name__’, ‘__qualname__’, ‘__doc__’, ‘__annotations__’)
UPDATES:(‘__dict__’, )
hello
this is the documentation of Hello Function
Help on function hello in module __main__:hello()
this is the documentation of Hello Function
通過使用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)
輸出:
UPDATED WRAPPER DATA
WRAPPER ASSIGNMENTS:(‘__module__’, ‘__name__’, ‘__qualname__’, ‘__doc__’, ‘__annotations__’)
UPDATES:(‘__dict__’,)
divide
Original Documentation of Divide
Help on partial in module __main__ object:divide = class partial(builtins.object)
| partial(func, *args, **keywords) - new function with partial application
| of the given arguments and keywords.
|
| Methods defined here:
|
| __call__(self, /, *args, **kwargs)
| Call self as a function.
|
| __delattr__(self, name, /)
| Implement delattr(self, name).
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| __reduce__(…)
| helper for pickle
|
| __repr__(self, /)
| Return repr(self).
|
| __setattr__(self, name, value, /)
| Implement setattr(self, name, value).
|
| __setstate__(…)
|
| ———————————————————————-
| Data descriptors defined here:
|
| __dict__
|
| args
| tuple of arguments to future partial calls
|
| func
| function object to use in future partial calls
|
| keywords
| dictionary of keyword arguments to future partial callsHelp on partial object:
class partial(builtins.object)
| partial(func, *args, **keywords) - new function with partial application
| of the given arguments and keywords.
|
| Methods defined here:
|
| __call__(self, /, *args, **kwargs)
| Call self as a function.
|
| __delattr__(self, name, /)
| Implement delattr(self, name).
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| __reduce__(…)
| helper for pickle
|
| __repr__(self, /)
| Return repr(self).
|
| __setattr__(self, name, value, /)
| Implement setattr(self, name, value).
|
| __setstate__(…)
|
| ———————————————————————-
| Data descriptors defined here:
|
| __dict__
|
| args
| tuple of arguments to future partial calls
|
| func
| function object to use in future partial calls
|
| keywords
| dictionary of keyword arguments to future partial calls
在此示例中,我們看到一半繼承了函數除法的基本module-level常量。當我們使用help(half)時,我們看到它部分地來自除法。值得注意的是,oneThird並非如此,因為help(oneThird)不會告訴我們父函數。
因此,通過以上說明,我們可以了解functools模塊中提供的update_wrapper(…)方法的用例。為了保留函數的元數據以供進一步使用,update_wrapper(…)是一種函數強大的工具,可以輕鬆使用。因此,該方法在裝飾器和局部裝飾的情況下被證明非常有用。
相關用法
- Python functools.wraps()用法及代碼示例
- Python Functools total_ordering()用法及代碼示例
- Python Functools用法及代碼示例
- Python Functools lru_cache()用法及代碼示例
- Python Functools cached_property()用法及代碼示例
注:本文由純淨天空篩選整理自tirtharajsengupta大神的英文原創作品 Python Functools – update_wrapper()。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。