Python 函数属性-范围
所以我有这个代码:Python 函数属性-范围,python,function,scope,attributes,decorator,Python,Function,Scope,Attributes,Decorator,所以我有这个代码: def collect_input(func): """ A decorator which adds an all_input attribute to the wrapped function. This attribute collects any input passed to the function. """ def wrapper(*args, **kwargs): wrapper.all_input.ap
def collect_input(func):
"""
A decorator which adds an all_input attribute to the wrapped function.
This attribute collects any input passed to the function.
"""
def wrapper(*args, **kwargs):
wrapper.all_input.append(*args)
return func(*args, **kwargs)
wrapper.all_input = []
return wrapper
@collect_input
def foo(bar):
print('in foo')
foo(5)
foo('spam')
print(foo.all_input)
我的问题是:如果在
collect\u input
范围中声明了foo.all\u input
,那么为什么您可以访问它呢?Python的优点是它有一组规则来处理它的对象,并且这些规则很少有例外
在本例中,修饰的函数只是一个普通的Python对象。一个碰巧也是可以调用的
collect\u input中的wrapper.all\u input=[]
行中发生的情况是,它在对象上设置了一个属性,在该点上命名为wrapper
,但该属性是将返回的对象,并在全局范围内取代foo
函数。这就是装饰师的工作方式
因此,让我们一步一步地把它弄清楚:
collect\u input
函数,该函数被设计为用作装饰器foo
函数,但在将其添加到全局范围之前,它被传递到collect\u input
函数中。这就是“@”语法的作用。在函数存在之前,修饰函数的方法是首先定义一个函数,然后用普通赋值替换它作为修饰器的返回值。因此,上述代码与:
def foo(…):
foo=收集输入(foo)foo
func将在新的wrapper
函数中调用。这个wrapper
函数:每次调用decoratorcollect\u input
时创建的新(函数)对象将取代最外层的foo
定义。您可以看到,在wrapper
的代码中有额外的代码来完成collect\u input
的目的:在一个列表中注释输入参数,并附加到其自身,然后继续调用原始函数-foo
collect\u input
返回的wrapper
对象取代了foo
,但在decorator调用中附加了all\u input
列表。因此,它可以作为foo
对象的属性在全局范围内访问,而不管它是在哪里定义的。请注意,在函数之外,不能按预期使用名称func
或wrapper
您可以看到
wrapper
如何取代foo
实际上,您并不是在访问foo.all\u input
而是wrapper.all\u input
,因为您使用了一个返回wrapper
函数的装饰程序来包装函数。
@collect_input
def foo(bar):
print(foo.__name__) # wrapper
print('in foo')