[英]Python Functions Can Have Attributes?
I'm very new to Python and I don't understand how functions themselves can seemingly have attributes. 我是Python的新手,我不明白函数本身看起来有什么属性。 In the code below, there is a function called f, and later in the code, something by the name of f.count is referenced.
在下面的代码中,有一个名为f的函数,稍后在代码中引用了名为f.count的函数。 How can a function, namely f, have a .count?
一个函数,即f,如何有一个.count? I'm getting an error message of: 'NoneType' object has no attribute 'count' on that line, so it obviously doesn't have that attribute yet.
我收到一条错误消息:'NoneType'对象在该行上没有属性'count',所以它显然还没有该属性。 How do I give it that attribute?
我该如何赋予它属性?
def fcount(n):
print n.__name__
@fcount
def f(n):
return n+2
for n in range(5):
print n
#print f(n)
print 'f count =',f.count #THE LINE CAUSING THE ERROR MENTIONED ABOVE
@fcount
def g(n):
return n*n
print 'g count =',g.count
print g(3)
print 'g count =',g.count
Edit: Added fcount(), which doesn't do anything much, and details about error. 编辑:添加了fcount(),它没有做任何事情,还有关于错误的详细信息。
Let's start with the definition of f
: 让我们从
f
的定义开始:
@fcount
def f(n):
return n+2
This defines a f
as the return value of a call to the function fcount
, which is used as a decorator (the leading @
) here. 这将
f
定义为对函数fcount
的调用的返回值,该函数在fcount
用作装饰器 (前导@
)。
This code is roughly equivalent with 此代码大致相当于
def f(n):
return n+2
f = fcount(f)
since the decorator – fcount
– does not return anything, f
is None
and not a function at the call site. 因为装饰器 -
fcount
- 不返回任何内容, f
是None
而不是调用站点的函数 。
In your case fcount
should return some function and add a count
attribute to that returned function. 在你的情况下,
fcount
应返回一些函数并为返回的函数添加count
属性。 Something useful (?) might be 有用的东西(?)可能是
def fcount(fn):
def wrapper(n):
wrapper.count += 1
return fn(n)
wrapper.count = 0
return wrapper
EDIT 编辑
As @jonrsharpe pointed out, a generalized decorator can forward positional and keyword arguments by capturing them with *args
and **kwargs
in the signature and expanding them in the same way when calling another function. 正如@jonrsharpe指出的那样,通用装饰器可以通过在签名中使用
*args
和**kwargs
捕获它们并在调用另一个函数时以相同的方式扩展它们来转发位置和关键字参数。 The names args
and kwargs
are used by convention. 名称
args
和kwargs
按惯例使用。
Python also has a helper function (a decorator itself) that can transfer information (name, docstring and signature information) from one function to another: functools.wraps
. Python还有一个辅助函数(一个装饰器本身),可以将信息(名称,文档字符串和签名信息)从一个函数传递到另一个函数:
functools.wraps
。 A complete example looks like this: 一个完整的示例如下所示:
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@decorator
def f(a, b, c=None):
"The useful f function"
pass
print f.__name__ # `f` rather than `wrapper`
print help(f) # `f(*args, **kwargs) The useful f function` rather than `wrapper(*args, **kwargs)`
The problem here is with your "decorator function", fcount
. 这里的问题是你的“装饰功能”,
fcount
。 A Python decorator function should return a function : Python装饰器函数应该返回一个函数 :
@decorates
def func(...):
...
is effectively: 有效地:
func = decorates(func)
In your case, the "decorator" fcount
only print
s, and won't return
anything; 在你的情况下,“装饰者”
fcount
只print
s,并且不会return
任何内容; hence using it will assign f = None
. 因此使用它将指定
f = None
。
The answer to your more general question is that functions, being Python objects like more-or-less everything else, certainly can have attributes. 你更普遍的问题的答案是,作为Python对象的函数,或多或少的其他东西,当然可以有属性。 To actually implement what you want, a decorator that counts how many times the decorated function is called, you could do:
要实际实现你想要的东西,一个装饰器计算装饰函数被调用的次数,你可以这样做:
def fcount(f):
"""Decorator function to count how many times f is called."""
def func(*args, **kwargs):
func.count += 1
return f(*args, **kwargs)
func.count = 0
return func
They can have attributes. 他们可以拥有属性。
This feature is rarely seen in the literature, but it has its uses, such as a simplified closure. 这个特征在文献中很少见,但它有其用途,例如简化的闭包。
By the way, the kind of counter code you asked about is explained in a Pycon 2014 video about decorators. 顺便说一下,你在问的关于装饰器的Pycon 2014视频中解释了你所询问的那种计数器代码。
Reference 参考
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.