如果您检测attach_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
然后
@log(logging.WARN, "example-param")
def somefunc(args):
return args
结果
>>>
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_wrapper 被调用两次。第一次它的func 是None,它返回一个带有第一个参数obj 的部分函数attach_wrapper 设置为 some_func。然后调用部分函数(装饰器机制的所有部分)并装饰函数。
attach_wrapper's obj 看起来像 some_func 但实际上是 some_func 包裹 wrapper - 看起来和感觉都一样,因为这就是 @wraps 的用途.
这里是更多细节,将inspect.stack 添加到instrumentation。
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
>>>
周围有一些更好的详细解释。如果我找到了,我会更新。