jac*_*ev6 11 python decorator functools python-decorators
def decorated(f):
@functools.wraps(f)
def wrapper():
return f()
return wrapper
@decorated
def g():
pass
Run Code Online (Sandbox Code Playgroud)
functools.wraps它的工作是保留以下名称g:
>>> g.__name__
'g'
Run Code Online (Sandbox Code Playgroud)
但是如果我传递一个参数g,我得到一个TypeError包含包装器的名称:
>>> g(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: wrapper() takes no arguments (1 given)
Run Code Online (Sandbox Code Playgroud)
这个名字来自哪里?它保存在哪里?有没有办法使异常看起来像g() takes no arguments?
名称来自代码对象; 函数和代码对象(包含要执行的字节码等)都包含该名称:
>>> g.__name__
'g'
>>> g.__code__.co_name
'wrapper'
Run Code Online (Sandbox Code Playgroud)
代码对象的属性是只读的:
>>> g.__code__.co_name = 'g'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute
Run Code Online (Sandbox Code Playgroud)
您必须创建一个全新的代码对象来重命名,请参阅我之前的答案,我在其中定义了一个函数来执行此操作; 使用rename_code_object()装饰函数上的函数:
>>> g = rename_code_object(g, 'g')
>>> g(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: g() takes no arguments (1 given)
Run Code Online (Sandbox Code Playgroud)
但请注意,这将完全掩盖正在运行的代码!您通常希望看到涉及装饰器包装器; 毕竟,它是抛出异常而不是原始函数的包装器.