By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,271 Members | 1,722 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,271 IT Pros & Developers. It's quick & easy.

Generators and Decorators doing my head in ..

P: n/a
Hi Can someone please help me understand this (i shouldn't have tried
to learn decorators and generators at the same time..).

Im trying to create a decorator that counts the number of times a
function is run. Somthing like:

def FunctionCounter():
n=0
while 1:
yield n
n=n+1

def logFunctionCalls(function):
print "Entering function:", function.__name__, ec.next()
return function

@logFunctionCalls
def doWork():
print "Doing Work"
doWork()

Where "ec" is a generator that is created inside logFunctionCalls if it
doesnt already exist.
Im thinking this has somthing to do with anonymous generators, but im
not sure how you create or access these..

Apologies in advance if this is moronic.

Sep 6 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Compare this to your original:

def logFunctionCalls(function):
ec = FunctionCounter()
def decoratedFunction(*args,**kwargs):
print "Entering function:", function.__name__, ec.next()
function(*args,**kwargs)
return decoratedFunction

@logFunctionCalls
def doWork():
print "Doing Work"

doWork()
doWork()

(This is a quick-and-dirty example, but it works. A proper iterator
would do more to preserve the identity, docstring, etc. of the
underlying doWork() function. See the decorator library page on the
Python Wiki, at http://wiki.python.org/moin/PythonDecoratorLibrary.)

Also, look into the treasure trove that is itertools, especially
itertools.count.

-- Paul

Sep 6 '05 #2

P: n/a
si*****@gmail.com wrote:
Im trying to create a decorator that counts the number of times a
function is run.


Your code doesn't work because decorators are run at function creation
time, not at function run time. Try this instead:
from itertools import count

def logFunctionCalls(function):
times = count()
def newfunction(*args, **kwargs):
print "Entering function:", function.__name__, times.next()
return function(*args, **kwargs)
newfunction.__doc__ = function.__doc__
newfunction.__name__ = function.__name__
return newfunction

@logFunctionCalls
def doWork():
print "Doing work..."
Sep 6 '05 #3

P: n/a
Paul McGuire wrote:
(snip)
(This is a quick-and-dirty example, but it works. A proper iterator


s/iterator/decorator/

(snip)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Sep 6 '05 #4

P: n/a
Fantastic, thanks Leif and Paul, My problem is that i thought the
decorator worked at the function runtime, not when the function gets
created.

Sep 6 '05 #5

P: n/a
I usually point out my decorator module
(http://www.phyast.pitt.edu/~micheles.../decorator.zip) to simplify
decorator usage. In this case you would use it as follows:

from decorator import decorator

@decorator # convert logFunctionCalls into a decorator
def logFunctionCalls(function, *args, **kwargs):
try: # increment the counter
function.counter += 1
except AttributeError: # first call, there is no counter attribute
function.counter = 1
print "Entering function:", function.__name__, function.counter
return function(*args, **kwargs)

@logFunctionCalls
def f():
pass

f()
f()
f()

help(f)

The whole point of the decorator module is that the signature of
the original function is left unchanged (i.e. in this case the
decorated f is still a thunk, not a generic function f(*args, **kw)).
HTH,

Michele Simionato

Sep 7 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.