Re: Decorator question: prefer class, but only function works

2011-11-14 Thread Russell E. Owen
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

2011-11-14 Thread Steven D'Aprano
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

2011-11-10 Thread Russell E. Owen
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

2011-11-10 Thread Ian Kelly
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

2011-01-27 Thread Mark Summerfield
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

2011-01-26 Thread Chris
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

2011-01-26 Thread Chris
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

2011-01-26 Thread MRAB

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

2011-01-26 Thread Thomas L. Shinnick

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

2010-10-17 Thread Lucasm
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

2010-10-16 Thread Lucasm
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

2010-10-16 Thread Peter Otten
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)

2009-06-20 Thread Martin P. Hellwig

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)

2009-06-19 Thread Martin P. Hellwig

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)

2009-06-19 Thread Bruno Desthuilliers

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

2007-05-23 Thread Steven W. Orr
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

2007-05-23 Thread Peter Otten
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

2007-05-23 Thread Giles Brown
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

2007-05-23 Thread Michele Simionato
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

2006-01-09 Thread Duncan Booth
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

2006-01-09 Thread Michele Simionato
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

2006-01-08 Thread Schüle Daniel
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

2006-01-08 Thread Frank Niessink
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

2006-01-08 Thread Ralf Schmitt
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

2006-01-08 Thread Bengt Richter
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

2006-01-08 Thread Schüle 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

  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