I read a question earlier asking if there was a times
method in Python, that would allow a function to be called n times in a row.
Everyone suggested for _ in range(n): foo()
but I wanted to try and code a different solution using a function decorator.
Here's what I have:
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")
When I run the program, I get the following exception:
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 'time开发者_StackOverflow中文版s'
So I suppose the decorator didn't work? How can I fix this?
Your decorator should return the function object:
def repeatable(func):
func.times = new.instancemethod(times, func, func.__class__)
return func
Now it returns nothing, so you actually change threeArgs in a None
This is because this:
@decorator
def func(...):
...
is more or less the same as:
def func(...):
....
func = decorator(func)
You're missing a return func
statement at the end of your repeatable
decorator.
Have you considered not adding it to specific functions and instead allowing its use with any function?
def times(n, func, *args, **kwds):
return [func(*args, **kwds) for _ in xrange(n)]
(I'm returning a list of return values, but you could write it to ignore them, similar to the for-loop you have in the question.)
Then where you would, with your version, use:
threeArgs.times(7, "one", two="rawr", three="foo")
You instead use:
times(7, threeArgs, "one", two="rawr", three="foo")
精彩评论