decorator question

F

Frank Niessink

Schüle Daniel said:
(1) fails to compile
is it possible to pass parameters to a decorator function?

Yes, I think this does what you want:

import time, sys

def timelogger(logfile=sys.stdout):
def actual_timelogger(function):
def wrapper(*a,**kw):
logfile.write("started at %s" % time.ctime())
t0 = time.time()
function(*a, **kw)
t1 = time.time()
logfile.write("ended at %s" % time.ctime())
logfile.write("diff = %f %s" % (t1-t0, "sec"))
return wrapper
return actual_timelogger

@timelogger(logfile=file("hierher", "a")) ### <<<<<< (1)
def loops(a,b,c):
sum = 0
for i in range(a):
for j in range(b):
for k in range(c):
sum += 1


loops(100,100,100)


Cheers, Frank
 
R

Ralf Schmitt

Schüle Daniel said:
hello NG,

consider this code

... def wrapper(*a,**kw):
... print "started at %s" % time.ctime()
... t0 = time.time()
... f(*a, **kw)
... t1 = time.time()
... print "ended at %s" % time.ctime()
... print "diff = ", t1-t0, "sec"
... return wrapper
...
... def loops(a,b,c):
... sum = 0
... for i in range(a):
... for j in range(b):
... for k in range(c):
... sum += 1
...
started at Sun Jan 8 23:19:19 2006
ended at Sun Jan 8 23:19:19 2006
diff = 0.000367164611816 sec

the code above works fine
but I am wondering wheather it's possible to
write something like this

... def wrapper(*a,**kw):
... logfile.write("started at %s" % time.ctime())
... t0 = time.time()
... f(*a, **kw)
... t1 = time.time()
... logfile.write("ended at %s" % time.ctime())
... logfile.write("diff = %f %s" % (t1-t0, "sec"))
... return wrapper

... def loops(a,b,c):
... sum = 0
... for i in range(a):
... for j in range(b):
... for k in range(c):
... sum += 1
...

(1) fails to compile
is it possible to pass parameters to a decorator function?

It's possible. The call to timelogger must return a function which
itself takes a function and returns one:

def timelogger(logfile=sys.stdout):
def deco(f):
def wrapper(*a,**kw):
logfile.write("started at %s" % time.ctime())
t0 = time.time()
f(*a, **kw)
t1 = time.time()
logfile.write("ended at %s" % time.ctime())
logfile.write("diff = %f %s" % (t1-t0, "sec"))
return wrapper
return deco
 
B

Bengt Richter

the code above works fine
but I am wondering wheather it's possible to
write something like this

... def wrapper(*a,**kw):
... logfile.write("started at %s" % time.ctime())
... t0 = time.time()
... f(*a, **kw)
... t1 = time.time()
... logfile.write("ended at %s" % time.ctime())
... logfile.write("diff = %f %s" % (t1-t0, "sec"))
... return wrapper

... def loops(a,b,c):
... sum = 0
... for i in range(a):
... for j in range(b):
... for k in range(c):
... sum += 1
...

(1) fails to compile
is it possible to pass parameters to a decorator function?
Yes, but then the function must return the same kind of thing
a bare decorator-function name would have, which is a function
able to take a single argument of a function and return a function.

So your decorator won't take f as an argument, just the optional logfile,
and it will return a function that does the wrapping like the original decorator.
... def deco(f):
... def wrapper(*a,**kw):
... logfile.write("started at %s\n" % time.ctime())
... t0 = time.time()
... f(*a, **kw)
... t1 = time.time()
... logfile.write("ended at %s\n" % time.ctime())
... logfile.write("diff = %f %s\n" % (t1-t0, "sec"))
... return wrapper
... return deco
... ... def foo(): pass
... started at Sun Jan 08 14:13:55 2006
ended at Sun Jan 08 14:13:55 2006
diff = 0.000000 sec started at Sun Jan 08 14:14:02 2006
ended at Sun Jan 08 14:14:02 2006
diff = 0.000000 sec ... def foo(dt): time.sleep(dt)
... started at Sun Jan 08 14:14:59 2006
ended at Sun Jan 08 14:15:04 2006
diff = 5.007000 sec started at Sun Jan 08 14:15:16 2006
ended at Sun Jan 08 14:15:17 2006
diff = 0.501000 sec
Regards,
Bengt Richter
 
?

=?ISO-8859-1?Q?Sch=FCle_Daniel?=

hello NG,

consider this code
.... def wrapper(*a,**kw):
.... print "started at %s" % time.ctime()
.... t0 = time.time()
.... f(*a, **kw)
.... t1 = time.time()
.... print "ended at %s" % time.ctime()
.... print "diff = ", t1-t0, "sec"
.... return wrapper
........ def loops(a,b,c):
.... sum = 0
.... for i in range(a):
.... for j in range(b):
.... for k in range(c):
.... sum += 1
....started at Sun Jan 8 23:19:19 2006
ended at Sun Jan 8 23:19:19 2006
diff = 0.000367164611816 sec

the code above works fine
but I am wondering wheather it's possible to
write something like this
.... def wrapper(*a,**kw):
.... logfile.write("started at %s" % time.ctime())
.... t0 = time.time()
.... f(*a, **kw)
.... t1 = time.time()
.... logfile.write("ended at %s" % time.ctime())
.... logfile.write("diff = %f %s" % (t1-t0, "sec"))
.... return wrapper
.... def loops(a,b,c):
.... sum = 0
.... for i in range(a):
.... for j in range(b):
.... for k in range(c):
.... sum += 1
....

(1) fails to compile
is it possible to pass parameters to a decorator function?

Regards, Daniel
 
?

=?ISO-8859-1?Q?Sch=FCle_Daniel?=

thx to all

now I understand how it works and why it should be done in this way
so it's possible to write more than only one declarator
.... l = [1]
.... def method(*a,**kw):
.... f(l, *a, **kw)
.... return method
........ l = [2]
.... def method(*a,**kw):
.... f(l, *a, **kw)
.... return method
........ @bar
.... def foobar(x,y,z):
.... print x
.... print y
.... print z
....[2]
[1]
1

x and y are already binded
by the way .. to l's lists are considered to be in closure?
Or what is the right denotation for them?
Can someone give me some pointers to the metaprogramming in Python?
links etc

Regards, Daniel
 
D

Duncan Booth

Bengt said:
Yes, but then the function must return the same kind of thing
a bare decorator-function name would have, which is a function
able to take a single argument of a function and return a function.

So your decorator won't take f as an argument, just the optional
logfile, and it will return a function that does the wrapping like the
original decorator.

This sounds to me like something that should be done using a decorator.
e.g. (everything from 'def timelogger' onwards is unchanged from the OP's
code):

def decoratorwithargs(f):
def wrapper(*args,**kw):
def inner(target):
return f(target, *args, **kw)
return inner
return wrapper

@decoratorwithargs
def timelogger(f, logfile=sys.stdout):
def wrapper(*a,**kw):
logfile.write("started at %s" % time.ctime())
t0 = time.time()
f(*a, **kw)
t1 = time.time()
logfile.write("ended at %s" % time.ctime())
logfile.write("diff = %f %s" % (t1-t0, "sec"))
return wrapper

@timelogger(file("hierher", "a")) ### <<<<<< (1)
def loops(a,b,c):
sum = 0
for i in range(a):
for j in range(b):
for k in range(c):
sum += 1

(I think the logfile output could do with some newlines.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Debugging decorator 0
Decorator question 2
Decorator question 4
recursive decorator 8
looping versus comprehension 0
decorator issue with modules dbus & gobject 2
accepts decorator 3
Decorator question 1

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,267
Latest member
WaylonCogb

Latest Threads

Top