2010-04-17 52 views
2

我之前读过一个问题,询问Python中是否存在times方法,该方法允许函数在连续调用n次。在运行时向函数对象添加方法

大家都建议for _ in range(n): foo()但我想尝试使用函数装饰器来编写不同的解决方案。

这是我有:

def times(self, n, *args, **kwargs): 
    for _ in range(n): 
     self.__call__(*args, **kwargs) 

import new 
def repeatable(func): 
    func.times = new.instancemethod(times, func, func.__class__) 

@repeatable 
def threeArgs(one, two, three): 
    print one, two, three 

threeArgs.times(7, "one", two="rawr", three="foo") 

当我运行程序时,我得到以下异常:

 
Traceback (most recent call last): 
    File "", line 244, in run_nodebug 
    File "C:\py\repeatable.py", line 24, in 
    threeArgs.times(7, "one", two="rawr", three="foo") 
AttributeError: 'NoneType' object has no attribute 'times' 

,所以我想这个装饰没有工作?我怎样才能解决这个问题?

+1

这种方法似乎是不太习惯,少个简单你正在替换的那个。 – 2010-04-17 23:09:32

回答

3

你的装饰应该返回函数对象:

def repeatable(func): 
    func.times = new.instancemethod(times, func, func.__class__) 
    return func 

现在,它没有返回值,所以你实际上是在没有改变threeArgs

这是因为这样的:

@decorator 
def func(...): 
    ... 

更或更少相同:

def func(...): 
    .... 
func = decorator(func) 
+0

真棒,我想我应该想出......哦,谢谢你的帮助 – 2010-04-17 21:30:27

1

您错过了装修器末尾的return func声明。

0

您是否考虑过不将其添加到特定功能,而是允许将其与任何函数一起使用?

def times(n, func, *args, **kwds): 
    return [func(*args, **kwds) for _ in xrange(n)] 

然后(我回来的返回值的列表,但你可以把它写忽略它们,类似的循环,你有问题。)

在那里你会,与您的版本,使用:

threeArgs.times(7, "one", two="rawr", three="foo") 

您改用:

times(7, threeArgs, "one", two="rawr", three="foo")