Python 为什么使用partial向函数添加属性
前几天我读了这篇文章,我不明白为什么在“日志装饰器”一节中使用了Python 为什么使用partial向函数添加属性,python,python-decorators,Python,Python Decorators,前几天我读了这篇文章,我不明白为什么在“日志装饰器”一节中使用了partial: attach\u wrapper未设置,用于在包装另一个函数的函数上设置某些属性: @attach_wrapper(wrapper) # Attaches "set_level" to "wrapper" as attribute def set_level(new_level): # Function that allows us to set log level
partial
:
attach\u wrapper
未设置,用于在包装另一个函数的函数上设置某些属性:
@attach_wrapper(wrapper) # Attaches "set_level" to "wrapper" as attribute
def set_level(new_level): # Function that allows us to set log level
nonlocal level
level = new_level
为什么不能用
setattr
直接在wrapper
上设置这些属性?如果插入attach\u wrapper
,可以看到它的func
参数是None
def attach_wrapper(obj, func=None): # Helper function that attaches function as attribute of an object
if func is None:
print(f'obj is {obj.__name__} - func is',func)
return partial(attach_wrapper, obj)
print(f'a_w:obj is {obj.__name__} - func is {func.__name__}')
setattr(obj, func.__name__, func)
return func
然后
导致
>>>
obj is somefunc - func is None
a_w:obj is somefunc - func is set_level
obj is somefunc - func is None
a_w:obj is somefunc - func is set_message
>>>
attach\u wrapper
被调用两次。它的func
第一次是None
,它返回一个分部函数attach\u wrapper
,其第一个参数obj
设置为some\u func
。然后调用分部(装饰器机制的所有部分),并对函数进行装饰
attach\u wrapper的
obj
看起来像some\u func
,但实际上它是some\u func
用wrapper
包装的-它的外观和感觉都是一样的,因为这就是它的用途
下面是将
inspect.stack
添加到仪器的更多细节
产生
>>>
called from: @attach_wrapper(wrapper) # Attaches "set_level" to "wrapper" as attribute
by function decorate
obj is somefunc, func is None
called from: def set_level(new_level): # Function that allows us to set log level
by function decorate
obj is somefunc, func is set_level
called from: @attach_wrapper(wrapper) # Attaches "set_message" to "wrapper" as attribute
by function decorate
obj is somefunc, func is None
called from: def set_message(new_message): # Function that allows us to set message
by function decorate
obj is somefunc, func is set_message
>>>
这里有一些更详细的解释。如果我找到一个,我将进行更新。它的使用方式是,如果调用
attach\u wrapper
函数时没有要包装的函数,它将返回一些东西,然后您可以使用其他函数调用这些东西,以便将多个附加到目标对象。例如,如果您有三个函数f
、g
和h
,以及一个对象foo
,您可以使用attach\u to\u foo=attach\u wrapper(foo)
创建一个“attacher”,然后将其与attach\u to\u foo(f)
、attach\u to\u foo(g)
和attach\u to\u foo(h)一起使用
以foo.f
、foo.g
和foo.h
结束
>>>
obj is somefunc - func is None
a_w:obj is somefunc - func is set_level
obj is somefunc - func is None
a_w:obj is somefunc - func is set_message
>>>
import inspect
def attach_wrapper(obj, func=None): # Helper function that attaches function as attribute of an object
print("called from: ", inspect.stack()[1].code_context[0].strip())
print("\tby function ", inspect.stack()[1].function)
if func is None:
print(f'\tobj is {obj.__name__}, func is {func}\n')
return partial(attach_wrapper, obj)
print(f'\tobj is {obj.__name__}, func is {func.__name__}\n')
setattr(obj, func.__name__, func)
return func
>>>
called from: @attach_wrapper(wrapper) # Attaches "set_level" to "wrapper" as attribute
by function decorate
obj is somefunc, func is None
called from: def set_level(new_level): # Function that allows us to set log level
by function decorate
obj is somefunc, func is set_level
called from: @attach_wrapper(wrapper) # Attaches "set_message" to "wrapper" as attribute
by function decorate
obj is somefunc, func is None
called from: def set_message(new_message): # Function that allows us to set message
by function decorate
obj is somefunc, func is set_message
>>>