Python函数可以有属性吗?

use*_*743 2 python attributes function decorator

我是Python的新手,我不明白函数本身看起来有什么属性.在下面的代码中,有一个名为f的函数,稍后在代码中引用了名为f.count的函数.一个函数,即f,如何有一个.count?我收到一条错误消息:'NoneType'对象在该行上没有属性'count',所以它显然还没有该属性.我该如何赋予它属性?

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
Run Code Online (Sandbox Code Playgroud)

编辑:添加了fcount(),它没有做任何事情,还有关于错误的详细信息.

Dav*_*lio 5

让我们从定义开始f:

@fcount
def f(n):
    return n+2
Run Code Online (Sandbox Code Playgroud)

这将a定义f为函数调用的返回值,该函数在此处fcount用作装饰器(前导@).

此代码大致相当于

def f(n):
    return n+2

f = fcount(f)
Run Code Online (Sandbox Code Playgroud)

由于装饰- fcount-不返回任何东西,fNone 和不是一个函数在调用点.

在你的情况下fcount应该返回一些函数并count为返回的函数添加一个属性.有用的东西(?)可能是

def fcount(fn):
    def wrapper(n):
        wrapper.count += 1
        return fn(n)
    wrapper.count = 0
    return wrapper
Run Code Online (Sandbox Code Playgroud)

编辑

正如@jonrsharpe指出的那样,通用装饰器可以通过在签名中捕获它们来转发位置和关键字参数,*args**kwargs在调用另一个函数时以相同的方式扩展它们.名称argskwargs惯例使用.

Python还有一个辅助函数(一个装饰器本身),可以将信息(名称,文档字符串和签名信息)从一个函数传递到另一个函数:functools.wraps.一个完整的示例如下所示:

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)`
Run Code Online (Sandbox Code Playgroud)