Re: Decorator question: prefer class, but only function works
In article CALwzidk11rqXjaxcwNKy5C2iotaBO_BcDWL_zFC6Rctue=4...@mail.gmail.com, Ian Kelly ian.g.ke...@gmail.com wrote: On Thu, Nov 10, 2011 at 2:52 PM, Russell E. Owen ro...@uw.edu wrote: I am trying to write a decorator that times an instance method and writes the results to a class member variable. For example: def timeMethod(func): def wrapper(self, *args, **keyArgs): t1 = time.time() res = func(self, *args, **keyArgs) duration = time.time() - t1 self.timings[func.__name__] = duration return res return wrapper This works, but I'm not very happy with the way self.timings is obtained. What do you feel is wrong with it? Oops, I stripped so much out of my example that I stripped the ugly bit. This is closer to the original and demonstrated the issue: def timeMethod(func): name = func.__name__ + Duration def wrapper(self, *args, **keyArgs): t1 = time.time() res = func(self, *args, **keyArgs) duration = time.time() - t1 self.timings[name] = duration return res return wrapper I don't like the way name is passed into wrapper. It works, but it looks like magic. A class offers an obvious place to save the information. Or I could just generate the name each time. I realize I'm showing the limits of my understanding of python binding of variable names, but I also think that if I find it confusing then others will, as well. sum(os.times()[:2]) instead, which (assuming your script is single-threaded) will more accurately count the actual CPU time spent in the function rather than real time, which could be quite different if the CPU is busy. Thanks for the suggestion. I decided to use time.clock(), which I understand gives basically the same information (at a resolution that is sufficient for my needs). Also, why do you need this? If you're just trying to evaluate the speed of your code, you should consider using a proper profiler or the timeit module. The former will tell you how much time is spent in each function, while the latter runs the code a large number of times in a loop, which gives you better precision for quick methods. It is for timing stages of a data processing pipeline. Only long-running tasks will be timed. Repeatedly running to get better times is neither practical nor necessary to get a good feeling of where the time is being spent. I first tried to write this as a class (for readability), and this did NOT work: class timeMethod(object): def __init__(self, func): self.func = func def __call__(self, *args, **keyArgs): t1 = time.time() res = self.func(*args, **keyArgs) duration = time.time() - t1 args[0].timings.set(self.func.__name__, duration) return res In the first case the wrapper is called as an unbound function, so it works. But in the second case the wrapper is called as a bound method -- thus args[0] is not func's class instance, and I can't get to the timings attribute. I prefer the function version myself, but to make this work you could add something like this (untested) to make your wrapper class a descriptor that tacks on the self argument: def __get__(self, instance, owner): from functools import partial if instance is None: return self return partial(self, instance) Thank you very much. I'll stick to the function, since it works, but it's nice to know how to work around the problem. -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question: prefer class, but only function works
On Mon, 14 Nov 2011 17:00:38 -0800, Russell E. Owen wrote: Oops, I stripped so much out of my example that I stripped the ugly bit. This is closer to the original and demonstrated the issue: def timeMethod(func): name = func.__name__ + Duration def wrapper(self, *args, **keyArgs): t1 = time.time() res = func(self, *args, **keyArgs) duration = time.time() - t1 self.timings[name] = duration return res return wrapper I don't like the way name is passed into wrapper. It works, but it looks like magic. A class offers an obvious place to save the information. Or I could just generate the name each time. The pattern you are seeing is called a closure, and it is a very important, if advanced, part of Python programming. Of course, you don't *have* to use closures, but it isn't scarily-advanced (like metaclass programming) but only moderately advanced, and there will be a lot of code out there using closures. http://en.wikipedia.org/wiki/Closure_(computer_science) Basically a closure is a function which remembers just enough of its current environment (the value of non-local variables) so that it can continue to work in the future, even if those non-locals change or disappear. I take it you are aware that timing code as shown is only suitable for long-running code, and not small snippets? For small snippets, you should use the timeit module. You might also find this recipe useful: http://code.activestate.com/recipes/577896/ -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Decorator question: prefer class, but only function works
I am trying to write a decorator that times an instance method and writes the results to a class member variable. For example: def timeMethod(func): def wrapper(self, *args, **keyArgs): t1 = time.time() res = func(self, *args, **keyArgs) duration = time.time() - t1 self.timings[func.__name__] = duration return res return wrapper This works, but I'm not very happy with the way self.timings is obtained. I first tried to write this as a class (for readability), and this did NOT work: class timeMethod(object): def __init__(self, func): self.func = func def __call__(self, *args, **keyArgs): t1 = time.time() res = self.func(*args, **keyArgs) duration = time.time() - t1 args[0].timings.set(self.func.__name__, duration) return res In the first case the wrapper is called as an unbound function, so it works. But in the second case the wrapper is called as a bound method -- thus args[0] is not func's class instance, and I can't get to the timings attribute. Unfortunately they are both pretty ugly. Is there a cleaner way to access the the instance of which func is a member? I was very disappointed it was not available when timeMethod was called/instantiated. -- Russell -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question: prefer class, but only function works
On Thu, Nov 10, 2011 at 2:52 PM, Russell E. Owen ro...@uw.edu wrote: I am trying to write a decorator that times an instance method and writes the results to a class member variable. For example: def timeMethod(func): def wrapper(self, *args, **keyArgs): t1 = time.time() res = func(self, *args, **keyArgs) duration = time.time() - t1 self.timings[func.__name__] = duration return res return wrapper This works, but I'm not very happy with the way self.timings is obtained. What do you feel is wrong with it? You probably should use sum(os.times()[:2]) instead, which (assuming your script is single-threaded) will more accurately count the actual CPU time spent in the function rather than real time, which could be quite different if the CPU is busy. Also, why do you need this? If you're just trying to evaluate the speed of your code, you should consider using a proper profiler or the timeit module. The former will tell you how much time is spent in each function, while the latter runs the code a large number of times in a loop, which gives you better precision for quick methods. I first tried to write this as a class (for readability), and this did NOT work: class timeMethod(object): def __init__(self, func): self.func = func def __call__(self, *args, **keyArgs): t1 = time.time() res = self.func(*args, **keyArgs) duration = time.time() - t1 args[0].timings.set(self.func.__name__, duration) return res In the first case the wrapper is called as an unbound function, so it works. But in the second case the wrapper is called as a bound method -- thus args[0] is not func's class instance, and I can't get to the timings attribute. I prefer the function version myself, but to make this work you could add something like this (untested) to make your wrapper class a descriptor that tacks on the self argument: def __get__(self, instance, owner): from functools import partial if instance is None: return self return partial(self, instance) HTH, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
On Jan 27, 2:42 am, Thomas L. Shinnick tshin...@io.com wrote: At 08:17 PM 1/26/2011, Chris wrote: I have a class (A, for instance) that possesses a boolean (A.b, for instance) that is liable to change over an instance's lifetime. Many of the methods of this class (A.foo, for instance) should not execute as long as this boolean is false, but should instead raise an exception. Can I use a decorator to implement this functionality? More exactly, could I define a function called 'checker' that accomplishes this: Mark Summerfield's book Programming in Python 3 has an example something like this (p.357) called 'positive_result'. I hesitate to quote the entire thing, so I'll quote only the inner 'half' of the decorator: def wrapper(*args, **kwargs): result = function(*args, **kwargs) assert result = 0, function.__name__ + () result isn't = 0 return result I would guess you would have to count on the first item in the methods' args to be self, and use that to test whether your attribute is false/true? Mark? def checker(f): ... class A(): b = True @checker def foo(self,...): print 'in foo' a = A() a.foo() a.b = False a.foo() would result in: 'in foo' Exception: ... This exact solution isn't necessary, just something that doesn't require me to have the clunky: def foo(self,...): if self.b: ... else: raise Exception('b attribute must be true before executing this method') in every method. Thanks, Chris Here's a simple example that I think does what you're after: ## #!/usr/bin/env python3 import functools def execute_if_valid(function): @functools.wraps(function) def wrapper(*args, **kwargs): if not args[0].valid: raise Exception(invalid instance) return function(*args, **kwargs) return wrapper class A: valid = True def foo(self): print(called foo() on a valid or invalid instance) @execute_if_valid def bar(self): print(called bar() on a valid instance) a = A() a.foo() a.bar() a.valid = False a.foo() a.bar() ## Here's its output: ## called foo() on a valid or invalid instance called bar() on a valid instance called foo() on a valid or invalid instance Traceback (most recent call last): File ./test.py, line 32, in module a.bar() File ./test.py, line 10, in wrapper raise Exception(invalid instance) Exception: invalid instance ## -- http://mail.python.org/mailman/listinfo/python-list
Decorator question
I have a class (A, for instance) that possesses a boolean (A.b, for instance) that is liable to change over an instance's lifetime. Many of the methods of this class (A.foo, for instance) should not execute as long as this boolean is false, but should instead raise an exception. Can I use a decorator to implement this functionality? More exactly, could I define a function called 'checker' that accomplishes this: def checker(f): ... class A(): b = True @checker def foo(self,...): print 'in foo' a = A() a.foo() a.b = False a.foo() would result in: 'in foo' Exception: ... This exact solution isn't necessary, just something that doesn't require me to have the clunky: def foo(self,...): if self.b: ... else: raise Exception('b attribute must be true before executing this method') in every method. Thanks, Chris -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
On Jan 26, 6:17 pm, Chris reilly.christop...@gmail.com wrote: I have a class (A, for instance) that possesses a boolean (A.b, for instance) that is liable to change over an instance's lifetime. Many of the methods of this class (A.foo, for instance) should not execute as long as this boolean is false, but should instead raise an exception. Can I use a decorator to implement this functionality? More exactly, could I define a function called 'checker' that accomplishes this: def checker(f): ... class A(): b = True @checker def foo(self,...): print 'in foo' a = A() a.foo() a.b = False a.foo() would result in: 'in foo' Exception: ... This exact solution isn't necessary, just something that doesn't require me to have the clunky: def foo(self,...): if self.b: ... else: raise Exception('b attribute must be true before executing this method') in every method. Thanks, Chris Sorry, discovered answer here: http://stackoverflow.com/questions/2309124/get-class-in-python-decorator -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
On 27/01/2011 02:17, Chris wrote: I have a class (A, for instance) that possesses a boolean (A.b, for instance) that is liable to change over an instance's lifetime. Many of the methods of this class (A.foo, for instance) should not execute as long as this boolean is false, but should instead raise an exception. Can I use a decorator to implement this functionality? More exactly, could I define a function called 'checker' that accomplishes this: def checker(f): ... class A(): b = True @checker def foo(self,...): print 'in foo' a = A() a.foo() a.b = False a.foo() would result in: 'in foo' Exception: ... This exact solution isn't necessary, just something that doesn't require me to have the clunky: def foo(self,...): if self.b: ... else: raise Exception('b attribute must be true before executing this method') in every method. How about this: def checker(func): def wrapper(self, *args, **kwargs): if not self.b: raise Exception('b attribute must be true before executing this method') return func(self, *args, **kwargs) return wrapper -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
At 08:17 PM 1/26/2011, Chris wrote: I have a class (A, for instance) that possesses a boolean (A.b, for instance) that is liable to change over an instance's lifetime. Many of the methods of this class (A.foo, for instance) should not execute as long as this boolean is false, but should instead raise an exception. Can I use a decorator to implement this functionality? More exactly, could I define a function called 'checker' that accomplishes this: Mark Summerfield's book Programming in Python 3 has an example something like this (p.357) called 'positive_result'. I hesitate to quote the entire thing, so I'll quote only the inner 'half' of the decorator: def wrapper(*args, **kwargs): result = function(*args, **kwargs) assert result = 0, function.__name__ + () result isn't = 0 return result I would guess you would have to count on the first item in the methods' args to be self, and use that to test whether your attribute is false/true? Mark? def checker(f): ... class A(): b = True @checker def foo(self,...): print 'in foo' a = A() a.foo() a.b = False a.foo() would result in: 'in foo' Exception: ... This exact solution isn't necessary, just something that doesn't require me to have the clunky: def foo(self,...): if self.b: ... else: raise Exception('b attribute must be true before executing this method') in every method. Thanks, Chris -- -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
On 16 Okt, 16:49, Peter Otten __pete...@web.de wrote: Lucasm wrote: I have a decorator problem and hope someone is able to help me out/ assist me. Thanks in advance. Suppose: ### Begin some_library_module ### def some_decorator(some_method): def inner(an_arg, *args, **kwargs): return some_method(an_arg, *args, **kwargs) return inner ### End some_library_module ### ### Begin my_module ### def my_decorator(some_method): def inner(self, an_arg, *args, **kwargs): self.do_something() At this point some_method() is just a Python function. You have to build a bound method or at least something that knows about self before you pass it on: bound_method = some_method.__get__(self) # bound_method = new.instancemethod(some_method, self) # bound_method = functools.partial(some_method, self) return some_decorator(bound_method)(an_arg, *args, **kwargs) return inner class My_Class(object): @my_decorator def my_method(self, an_arg, *args, **kwargs): print self, an_arg def do_something(self): pass ### End My_module ### My_Class().my_method('bla') TypeError: my_method() takes at least 2 arguments (1 given) `self` is lost in the process, because my decorator does use it and the library's doesn't. I fail to find a way to keep self in the args without modifying the library. Thanks a lot! I didn't expect that it would be that easy :) Regards, Lucas -- http://mail.python.org/mailman/listinfo/python-list
Decorator question
Hello, I have a decorator problem and hope someone is able to help me out/ assist me. Thanks in advance. Suppose: ### Begin some_library_module ### def some_decorator(some_method): def inner(an_arg, *args, **kwargs): return some_method(an_arg, *args, **kwargs) return inner ### End some_library_module ### ### Begin my_module ### def my_decorator(some_method): def inner(self, an_arg, *args, **kwargs): self.do_something() return some_decorator(some_method)(an_arg, *args, **kwargs) return inner class My_Class(object): @my_decorator def my_method(self, an_arg, *args, **kwargs): print self, an_arg def do_something(self): pass ### End My_module ### My_Class().my_method('bla') TypeError: my_method() takes at least 2 arguments (1 given) `self` is lost in the process, because my decorator does use it and the library's doesn't. I fail to find a way to keep self in the args without modifying the library. -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
Lucasm wrote: I have a decorator problem and hope someone is able to help me out/ assist me. Thanks in advance. Suppose: ### Begin some_library_module ### def some_decorator(some_method): def inner(an_arg, *args, **kwargs): return some_method(an_arg, *args, **kwargs) return inner ### End some_library_module ### ### Begin my_module ### def my_decorator(some_method): def inner(self, an_arg, *args, **kwargs): self.do_something() At this point some_method() is just a Python function. You have to build a bound method or at least something that knows about self before you pass it on: bound_method = some_method.__get__(self) # bound_method = new.instancemethod(some_method, self) # bound_method = functools.partial(some_method, self) return some_decorator(bound_method)(an_arg, *args, **kwargs) return inner class My_Class(object): @my_decorator def my_method(self, an_arg, *args, **kwargs): print self, an_arg def do_something(self): pass ### End My_module ### My_Class().my_method('bla') TypeError: my_method() takes at least 2 arguments (1 given) `self` is lost in the process, because my decorator does use it and the library's doesn't. I fail to find a way to keep self in the args without modifying the library. -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question (how to test if decorated function is in a class)
Bruno Desthuilliers wrote: cut Short answer: this makes no sense. Absolutely right, took me a while to figure that out though :-) Lesson learned (again): If it really seems impossible to do something in Python, it is likely the proposed solution is flawed. -- MPH http://blog.dcuktec.com 'If consumed, best digested with added seasoning to own preference.' -- http://mail.python.org/mailman/listinfo/python-list
Decorator question (how to test if decorated function is in a class)
Hi all, I have been trying out to wrap my mind around the advantages of decorators and thought I found a use in one of my experiments. (see code after my sig). Although it works, I think it should be able to do it better. My particular problem is that I want to remove an argument (say always the first one) when the decorated function is called. However if the function is defined in a class the first argument is self and thus the second argument should be removed. Since I like to have a more general DRY approach I want to test if the decorated function is defined in a class or not thus knowing that the first argument is self and must be preserved. I tried different approaches but all didn't work and looked very unpythonic (looking at the attributes, descriptors namespaces, id() of the function, the first argument and the decorator itself). So is there a way to find out if the first argument is 'self' without making a false positive if the first argument is a class instance passed to a function? -- MPH http://blog.dcuktec.com 'If consumed, best digested with added seasoning to own preference.' code: class Decorator(object): When used as Decorator(argument) returns a decorator def __init__(self, key): self.key = key def __call__(self, function): Return a decorator def decorator(*arg_tuple, **arg_dict): The decorator test if the arguments contain a valid key if arg_tuple[0] == self.key: # This means it is a simple function, so check and strip it arg_list = arg_tuple[1::] return(function(*arg_list, **arg_dict)) elif arg_tuple[1] == self.key: # This means it is a class method, check it, # strip (but retain self) arg_list = arg_tuple arg_list = arg_list[0:1] + arg_list[2::] return(function(*arg_list, **arg_dict)) else: # The key was invalid return('invalid') return(decorator) class Test(object): @Decorator('key') def test(self, data): return(data) @Decorator('key') def function_2(self, data): return(data) @Decorator('key') def function_3(self, data): return(data) @Decorator('key') def test_f(data): return(data) # Test starts here test_c = Test() print(test_c.test('key', 'data')) print(test_f('key', 'data')) print(test_c.test('invalid', 'data')) print(test_f('invalid', 'data')) -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question (how to test if decorated function is in a class)
Martin P. Hellwig a écrit : Hi all, I have been trying out to wrap my mind around the advantages of decorators and thought I found a use in one of my experiments. (see code after my sig). Although it works, I think it should be able to do it better. My particular problem is that I want to remove an argument (say always the first one) when the decorated function is called. However if the function is defined in a class the first argument is self and thus the second argument should be removed. You'll have the same problem with a function defined outside a class then attached to the class, ie: def func(...): pass class Foo(object): pass Foo.meth = func Since I like to have a more general DRY approach I want to test if the decorated function is defined in a class or not thus knowing that the first argument is self and must be preserved. Short answer: this makes no sense. I tried different approaches but all didn't work and looked very unpythonic (looking at the attributes, descriptors namespaces, id() of the function, the first argument and the decorator itself). So is there a way to find out if the first argument is 'self' without making a false positive if the first argument is a class instance passed to a function? The solution to your problem is elsewhere... Read the doc about the descriptor protocol, and how it's implemented by the function type to turn functions into methods when they are looked up as attribute of a class... -- http://mail.python.org/mailman/listinfo/python-list
Decorator question
I just discovered decorators. Very cool. My question is that I can't figure out how to make a decorator not be restricted to a function so it would also work on a method. Here's my code: def g(expr): def rpt(func): def wrapper(t): for ii in range(expr): print ii, func(t) wrapper.__name__ = func.__name__ wrapper.__dict__ = func.__dict__ wrapper.__doc__ = func.__doc__ return func return wrapper return rpt @g(20) def f(s): print 's=%s'%s f('Hello') It works fine, but now I want to apply the same decorator to a class method. class KK: # @g(20) This obviously doesn't work. def f(self, s): print 's= %s'%s k = KK() k.f('Hello') Is there a trick I need? TIA -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
Steven W. Orr wrote: I just discovered decorators. Very cool. My question is that I can't figure out how to make a decorator not be restricted to a function so it would also work on a method. Here's my code: @g(20) def f(s): print 's=%s'%s f('Hello') Here you are calling f() with one string argument. It works fine, but now I want to apply the same decorator to a class method. class KK: # @g(20) This obviously doesn't work. def f(self, s): print 's= %s'%s k = KK() k.f('Hello') Here you are calling KK.f() with two arguments (an implicit KK instance and the explicit Hello string). Both calls are channeled through wrapper(t) which expects exactly one parameter. Is there a trick I need? Change wrapper() to accept an arbitrary number of arguments: def g(expr): def rpt(func): def wrapper(*args): for ii in range(expr): print ii, func(*args) wrapper.__name__ = func.__name__ wrapper.__dict__ = func.__dict__ wrapper.__doc__ = func.__doc__ return func return wrapper return rpt Peter -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
On 23 May, 14:46, Steven W. Orr [EMAIL PROTECTED] wrote: I just discovered decorators. Very cool. My question is that I can't figure out how to make a decorator not be restricted to a function so it would also work on a method. Here's my code: def g(expr): def rpt(func): def wrapper(t): for ii in range(expr): print ii, func(t) wrapper.__name__ = func.__name__ wrapper.__dict__ = func.__dict__ wrapper.__doc__ = func.__doc__ return func return wrapper return rpt @g(20) def f(s): print 's=%s'%s f('Hello') It works fine, but now I want to apply the same decorator to a class method. class KK: # @g(20) This obviously doesn't work. def f(self, s): print 's= %s'%s k = KK() k.f('Hello') Is there a trick I need? TIA -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net For this kind of decorator where you don't care about the values of the arguments you could just use *args (and perhaps **kwargs too)? def g(expr): def rpt(func): def wrapper(*args, **kwargs): for ii in range(expr): print ii, func(*args, **kwargs) wrapper.__name__ = func.__name__ wrapper.__dict__ = func.__dict__ wrapper.__doc__ = func.__doc__ return func return wrapper return rpt Giles -- http://mail.python.org/mailman/listinfo/python-list
Re: Decorator question
If you are using Python 2.5, you can use functools.update_wrapper to simplify your life. For instance from functools import update_wrapper # requires Python 2.5 def trace(func): def wrapper(*args,**kw): print 'calling %s with args %s' % (func.__name__,args) return func(*args,**kw) return update_wrapper(wrapper,func) class P(object): @classmethod @trace def c(cls): print cls p =P() p.c() Also, you can have a look to my own decorator module: http://www.phyast.pitt.edu/~micheles/python/decorator.zip HTH, Michele Simionato -- http://mail.python.org/mailman/listinfo/python-list
Re: decorator question
Bengt Richter wrote: 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. 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.) -- http://mail.python.org/mailman/listinfo/python-list
Re: decorator question
Schüle Daniel wrote: Can someone give me some pointers to the metaprogramming in Python? links etc Check the Python Wiki. For the decorators in particular I wrote a module that you may find useful. See http://www.phyast.pitt.edu/~micheles/python/decorator.zip http://www.phyast.pitt.edu/~micheles/python/documentation.html -- http://mail.python.org/mailman/listinfo/python-list
decorator question
hello NG, consider this code def timelogger(f): ... 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 ... import time @timelogger ... 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 function wrapper at 0x402eec34 loops(10,10,10) 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 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 import time @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 ... (1) fails to compile is it possible to pass parameters to a decorator function? Regards, Daniel -- http://mail.python.org/mailman/listinfo/python-list
Re: decorator question
Schüle Daniel wrote: (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 -- http://mail.python.org/mailman/listinfo/python-list
Re: decorator question
Schüle Daniel schrieb: hello NG, consider this code def timelogger(f): ... 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 ... import time @timelogger ... 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 function wrapper at 0x402eec34 loops(10,10,10) 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 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 import time @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 ... (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 Regards, Daniel -- http://mail.python.org/mailman/listinfo/python-list
Re: decorator question
On Sun, 08 Jan 2006 23:26:28 +0100, =?ISO-8859-1?Q?Sch=FCle_Daniel?= [EMAIL PROTECTED] wrote: [...] the code above works fine but I am wondering wheather it's possible to write something like this 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 import time @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 ... (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. import sys, time def timelogger(logfile=sys.stdout): ...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 ... @timelogger() # stdout ... def foo(): pass ... foo() started at Sun Jan 08 14:13:55 2006 ended at Sun Jan 08 14:13:55 2006 diff = 0.00 sec foo() started at Sun Jan 08 14:14:02 2006 ended at Sun Jan 08 14:14:02 2006 diff = 0.00 sec @timelogger() # stdout ... def foo(dt): time.sleep(dt) ... foo(5) started at Sun Jan 08 14:14:59 2006 ended at Sun Jan 08 14:15:04 2006 diff = 5.007000 sec foo(.5) 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: decorator question
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 def foo(f): ... l = [1] ... def method(*a,**kw): ... f(l, *a, **kw) ... return method ... def bar(f): ... l = [2] ... def method(*a,**kw): ... f(l, *a, **kw) ... return method ... @foo ... @bar ... def foobar(x,y,z): ... print x ... print y ... print z ... foobar(1) [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 -- http://mail.python.org/mailman/listinfo/python-list