Python函数可以有属性吗?

时间:2014-03-10 17:15:43

标签: python function attributes 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

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

3 个答案:

答案 0 :(得分:5)

让我们从f

的定义开始
@fcount
def f(n):
    return n+2

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

此代码与

大致相同
def f(n):
    return n+2

f = fcount(f)

由于装饰器 - fcount - 没有返回任何内容,fNone ,而不是呼叫网站上的功能

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

def fcount(fn):
    def wrapper(n):
        wrapper.count += 1
        return fn(n)
    wrapper.count = 0
    return wrapper

修改

正如@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)`

答案 1 :(得分:3)

这里的问题在于你的“装饰功能”,fcount。 Python装饰器函数应该返回一个函数

@decorates
def func(...):
    ...

实际上是:

func = decorates(func)

在您的情况下,“装饰者”fcountprint,并且不会return任何内容;因此使用它将分配f = None

你的更普遍的问题的答案是,作为Python对象的函数,或多或少的其他东西,当然可以有属性。要实际实现你想要的东西,一个计算装饰函数调用次数的装饰器,你可以这样做:

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

答案 2 :(得分:0)

Python函数是第一类对象。

他们可以拥有属性。

此功能在文献中很少见,但它有其用途,例如简化的闭包。

顺便说一句,你在问的关于装饰者的Pycon 2014视频中解释了你所询问的那种计数器代码。

<强>参考