RE: Decorator help

2013-07-04 Thread Joseph L. Casale
Well, technically it's

func.func_closure[0].cell_contents.__name__

but of course you cannot know that for the general case.

Hah, I admit I lacked perseverance in looking at this in PyCharms debugger as I 
missed
that.

Much appreciated!
jlc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-07-04 Thread Joshua Landau
On 4 July 2013 06:39, Peter Otten __pete...@web.de wrote:
 Joshua Landau wrote:

 On 3 July 2013 23:19, Joshua Landau joshua.landau...@gmail.com wrote:
 If you don't want to do that, you'd need to use introspection of a
 remarkably hacky sort. If you want that, well, it'll take a mo.

 After some effort I'm pretty confident that the hacky way is impossible.

 Well, technically it's

 func.func_closure[0].cell_contents.__name__

 but of course you cannot know that for the general case.

I didn't want to do something like that as it implies a lot of
knowledge about the function -- which implies that there's no reason
to do it hacky in the first place. I was using
inspect.getclosurevars(func).nonlocals and that coerces to a
dictionary first. It's the correct way of doing things. But you
never know what name the function inside the wrapper is bound to, so I
didn't accept that.

Also, your method has undefined behaviour AFAIK -- the order of
func_closure is compiler-dependant. If you want to do something like
this, I recommend my method (but it doesn't work for the general case
in the slightest):

inspect.getclosurevars(func).nonlocals[func].__name__

If you can't assume the name it's stored in, but you can know the
order of closure variables *then* use Peter's. But again, don't use
either; it's impossible just as I said.
-- 
http://mail.python.org/mailman/listinfo/python-list


Decorator help

2013-07-03 Thread Joseph L. Casale
I have a set of methods which take args that I decorate twice,

def wrapped(func):
def wrap(*args, **kwargs):
try:
val = func(*args, **kwargs)
# some work
except BaseException as error:
log.exception(error)
return []
return wrap

def wrapped_again(length):
def something(func):
def wrapped_func(*args, **kwargs):
values = func(*args, **kwargs)
# do some work
return values
return wrapped_func
return something

So the methods wrapped are as follows:

@wrapped_again(12)
@wrapped
def class_method(self, **kwargs):
#

Is it possible to get the name of the original method (class_method) from 
within wrapped_func inside wrapped_again?
Thanks!
jlc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-07-03 Thread Joshua Landau
On 3 July 2013 23:09, Joseph L. Casale jcas...@activenetwerx.com wrote:
 I have a set of methods which take args that I decorate twice,

 def wrapped(func):
 def wrap(*args, **kwargs):
 try:
 val = func(*args, **kwargs)
 # some work
 except BaseException as error:
 log.exception(error)
 return []
 return wrap

 def wrapped_again(length):
 def something(func):
 def wrapped_func(*args, **kwargs):
 values = func(*args, **kwargs)
 # do some work
 return values
 return wrapped_func
 return something

 So the methods wrapped are as follows:

 @wrapped_again(12)
 @wrapped
 def class_method(self, **kwargs):
 #

 Is it possible to get the name of the original method (class_method) from 
 within wrapped_func inside wrapped_again?
 Thanks!

Normally  you'd want to use functools.wraps;

def wrapped(func):
@functools.wraps
def wrap(*args, **kwargs): ...
return wrap

def wrapped_again(length):
@functools.wraps
def something(func): ...
return something

@wrapped_again(12)
@wrapped
def class_method(self, **kwargs):


And then the name is carried, as with docstrings.

If you don't want to do that, you'd need to use introspection of a
remarkably hacky sort. If you want that, well, it'll take a mo.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-07-03 Thread Joshua Landau
On 3 July 2013 23:19, Joshua Landau joshua.landau...@gmail.com wrote:
 If you don't want to do that, you'd need to use introspection of a
 remarkably hacky sort. If you want that, well, it'll take a mo.

After some effort I'm pretty confident that the hacky way is impossible.
-- 
http://mail.python.org/mailman/listinfo/python-list


RE: Decorator help

2013-07-03 Thread Joseph L. Casale
 If you don't want to do that, you'd need to use introspection of a
 remarkably hacky sort. If you want that, well, it'll take a mo.

 After some effort I'm pretty confident that the hacky way is impossible.

Hah, I fired it in PyCharm's debugger and spent a wack time myself, thanks
for the confirmation, I'll give functools a shot.

Thanks a lot,
jlc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-07-03 Thread Peter Otten
Joshua Landau wrote:

 On 3 July 2013 23:19, Joshua Landau joshua.landau...@gmail.com wrote:
 If you don't want to do that, you'd need to use introspection of a
 remarkably hacky sort. If you want that, well, it'll take a mo.
 
 After some effort I'm pretty confident that the hacky way is impossible.

Well, technically it's 

func.func_closure[0].cell_contents.__name__

but of course you cannot know that for the general case.

-- 
http://mail.python.org/mailman/listinfo/python-list


RE: Decorator help

2013-03-30 Thread Joseph L. Casale
 When you say class vars, do you mean variables which hold classes?


You guessed correctly, and thanks for pointing out the ambiguity in my 
references.


 The one doesn't follow from the other. Writing decorators as classes is 

 fairly unusual. Normally, they will be regular functions.


I see, this I didn't know. I'll stick to this guideline now.


 A more complicated case is where you need to do some pre-processing, and 
 you *don't* want that calculation repeated every time the method is
 called. Decorators are fantastic for that case too, but here you cannot
 access instance attributes, since the instance doesn't exist yet. But you
 can access *class attributes*, as more-or-less ordinary local variables
 *inside* the class definition. Here's a working sketch of the sort of
 thing you can do. Copy and paste the following into a Python interactive
 session, and then see if you can follow what is being done when.

 Is your mind boggled yet? :-)


Steven,
That was some of the coolest stuff I have seen a while. I had to wait until I 
had
enough time to actually run this through and utilize it my own work. I haven't
enjoyed Python this much since I first started using it.


Can't thank you enough for the time and thorough example, that imparted loads
of insight.


jlc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-03-30 Thread 88888 Dihedral
Jason Swails於 2013年3月28日星期四UTC+8上午4時33分08秒寫道:
 On Wed, Mar 27, 2013 at 3:49 PM, Joseph L. Casale jca...@activenetwerx.com 
 wrote:
 
 I have a class which sets up some class vars, then several methods that are 
 passed in data
 
 and do work referencing the class vars.
 
 
 
 
 
 I want to decorate these methods, the decorator needs access to the class 
 vars, so I thought
 
 about making the decorator its own class and allowing it to accept args.
 
 
 
 
 
 I was hoping to do all the work on in_data from within the decorator, which 
 requires access
 
 to several MyClass vars. Not clear on the syntax/usage with this approach 
 here, any guidance
 
 would be greatly appreciated!
 
 
 
 My guess is that you don't quite 'get' decorators yet (since I remember 
 similar types of questions when trying to learn them myself).  Decorators 
 execute when the class type itself is being built (e.g., when a module is 
 first imported at runtime).  So decorators will never take instance variables 
 as arguments (nor should they, since no instance can possibly exist when they 
 execute).  Bear in mind, a decorator should take a callable as an argument 
 (and any number of 'static' parameters you want to assign it), and return 
 another callable.
 
 
 
 I provide an example decorator using the format the I typically adopt below 
 (where the decorator is a simple function, not a class):
 
 
 def my_decorator(fcn):

I might add default parameters here  if I am programming 
in python to save the troubles of subclassing
similar decorators.

But that is only the stylish problem in python.

I might need to translate the decorator part into cython 
or c/c++ in the future.


     Decorator for a function 
 
    def new_fcn(self, *args, **kwargs):
        This is the new function that we will return. 
       # You can access any instance variables here
       returnval = fcn(self, *args, **kwargs)
 
       # Do anything else here with instance variables
       return returnval # or any other return value you want
    
    return new_fcn
 
 
 Notice here I define a new_fcn callable function that takes self and an 
 arbitrary argument/keyword-argument list, and I return this function (which 
 does not get called) to replace the function I passed in.  You can use 
 instance variables inside new_fcn since new_fcn is called by instances of 
 MyClass.  This is a very simple type of decorator, but hopefully helps 
 illustrate what decorators are.  There is a particularly good thread on SO 
 with information about decorators here: 
 http://stackoverflow.com/questions/739654/understanding-python-decorators
 
 
 
 Hope this helps,
 Jason

-- 
http://mail.python.org/mailman/listinfo/python-list


Decorator help

2013-03-27 Thread Joseph L. Casale
I have a class which sets up some class vars, then several methods that are 
passed in data
and do work referencing the class vars.


I want to decorate these methods, the decorator needs access to the class vars, 
so I thought
about making the decorator its own class and allowing it to accept args.


I was hoping to do all the work on in_data from within the decorator, which 
requires access
to several MyClass vars. Not clear on the syntax/usage with this approach here, 
any guidance
would be greatly appreciated!


Class MyDecorator(object):

    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2
    ...


Class MyClass(object):
    def __init__(self):
        self.var_a = 
    
    @MyDecorator(...)
    def meth_one(self, in_data):
        ...


Thanks!
jlc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-03-27 Thread Arnaud Delobelle
On 27 March 2013 19:49, Joseph L. Casale jcas...@activenetwerx.com wrote:
 I have a class which sets up some class vars, then several methods that are 
 passed in data
 and do work referencing the class vars.


 I want to decorate these methods, the decorator needs access to the class 
 vars, so I thought
 about making the decorator its own class and allowing it to accept args.


 I was hoping to do all the work on in_data from within the decorator, which 
 requires access
 to several MyClass vars. Not clear on the syntax/usage with this approach 
 here, any guidance
 would be greatly appreciated!


 Class MyDecorator(object):

 def __init__(self, arg1, arg2):
 self.arg1 = arg1
 self.arg2 = arg2
 ...


 Class MyClass(object):
 def __init__(self):
 self.var_a = 
 
 @MyDecorator(...)
 def meth_one(self, in_data):
 ...

I don't really understand what you are trying to do.  It would be
easier if you had some code that tried to do something (even if it
doesn't quite work).

-- 
Arnaud
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-03-27 Thread Jason Swails
On Wed, Mar 27, 2013 at 3:49 PM, Joseph L. Casale jcas...@activenetwerx.com
 wrote:

 I have a class which sets up some class vars, then several methods that
 are passed in data
 and do work referencing the class vars.


 I want to decorate these methods, the decorator needs access to the class
 vars, so I thought
 about making the decorator its own class and allowing it to accept args.


 I was hoping to do all the work on in_data from within the decorator,
 which requires access
 to several MyClass vars. Not clear on the syntax/usage with this approach
 here, any guidance
 would be greatly appreciated!


My guess is that you don't quite 'get' decorators yet (since I remember
similar types of questions when trying to learn them myself).  Decorators
execute when the class type itself is being built (e.g., when a module is
first imported at runtime).  So decorators will never take instance
variables as arguments (nor should they, since no instance can possibly
exist when they execute).  Bear in mind, a decorator should take a callable
as an argument (and any number of 'static' parameters you want to assign
it), and return another callable.

I provide an example decorator using the format the I typically adopt below
(where the decorator is a simple function, not a class):

def my_decorator(fcn):
Decorator for a function 
   def new_fcn(self, *args, **kwargs):
   This is the new function that we will return. 
  # You can access any instance variables here
  returnval = fcn(self, *args, **kwargs)
  # Do anything else here with instance variables
  return returnval # or any other return value you want

   return new_fcn

Notice here I define a new_fcn callable function that takes self and an
arbitrary argument/keyword-argument list, and I return this function (which
does not get called) to replace the function I passed in.  You can use
instance variables inside new_fcn since new_fcn is called by instances of
MyClass.  This is a very simple type of decorator, but hopefully helps
illustrate what decorators are.  There is a particularly good thread on SO
with information about decorators here:
http://stackoverflow.com/questions/739654/understanding-python-decorators

Hope this helps,
Jason
-- 
http://mail.python.org/mailman/listinfo/python-list


RE: Decorator help

2013-03-27 Thread Joseph L. Casale
 So  decorators will never take instance variables as arguments (nor should 
they, since no instance
 can possibly exist when they execute).


Right, I never thought of it that way, my only use of them has been trivial, in 
non class scenarios so far.


 Bear in mind, a decorator should take a callable as an argument (and any 
 number of 'static' parameters
 you want to assign  it), and return another callable.


Got it, and thanks for the detail as well!
jlc
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-03-27 Thread Steven D'Aprano
On Wed, 27 Mar 2013 19:49:54 +, Joseph L. Casale wrote:

 I have a class which sets up some class vars, then several methods that
 are passed in data and do work referencing the class vars.


When you say class vars, do you mean variables which hold classes? Like 
string vars are variables which hold strings, and int vars are 
variables that hold ints? Classes (also known as types) are first-class 
objects in Python (no pun intended), unlike Java, and so you can store 
them in lists, returns them from functions, and bind them in variables.

for aclass in list_of_classes:
do_something_with(aclass)


Consequently, when people talk about class variables, it is ambiguous, 
which is why we prefer to use class attribute to refer to attributes on 
the class. For example:

class Parrot(object):
breed = Norwegian Blue  # this is a class attribute

def __init__(self, name=Polly):
self.name = name  # this is an instance attribute

def speak(self):
s = %s the %s says, 'Hello sailor!'
print(s % (self.name, self.breed))


Class attributes are attached to the class object itself, and are shared 
between all instances. Instance attributes are attached to the instance, 
where they over-ride any class attribute of the same name, and are not 
shared.

In the following I am going to assume that you actually are talking about 
attributes, rather than an actual variable holding a class.


 I want to decorate these methods, the decorator needs access to the
 class vars, so I thought about making the decorator its own class and
 allowing it to accept args.

The one doesn't follow from the other. Writing decorators as classes is 
fairly unusual. Normally, they will be regular functions. If your 
decorator needs to store so much state that it needs to be a class, 
you're probably trying to do too much from a single decorator.

There's more that you need to describe, such as what it is that the 
decorator actually does, and whether it does it once, when the decorator 
is called, or repeatedly, when the decorated method is called.

The second case is the easiest. Suppose you have a class like this, with 
many methods which have code in common. Here's a toy example:


def MyClass(object):
x = class attribute

def __init__(self, y):
self.y = y

def spam(self):
do_stuff(self.x)
do_stuff(self.y)
print(spam spam spam spam)

def ham(self):
do_stuff(self.x)
do_stuff(self.y)
return ham, a growing boy's best friend

def eggs(self, food=bacon):
do_stuff(self.x)
do_stuff(self.y)
return green eggs and %s % food



A simple decorator function can simplify the common code:


import functools

def decorate(func):
@functools.wraps(func)
def inner(self, *args, **kwargs):
 # call the common, repeated, code
 do_stuff(self.x)
 do_stuff(self.y)
 # call the function being wrapped
 return func(self, *args, **kwargs)
return inner


def MyClass(object):
x = class attribute

def __init__(self, y):
self.y = y

@decorate
def spam(self):
print(spam spam spam spam)

@decorate
def ham(self):
return ham, a growing boy's best friend

@decorate
def eggs(self, food=bacon):
return green eggs and %s % food



Notice that because the decorator doesn't do any work until the decorated 
function is called, there is no difficulty in accessing attributes 
regardless of whether they are attached to the class or the instance. 
They won't be looked up until self is known.


A more complicated case is where you need to do some pre-processing, and 
you *don't* want that calculation repeated every time the method is 
called. Decorators are fantastic for that case too, but here you cannot 
access instance attributes, since the instance doesn't exist yet. But you 
can access *class attributes*, as more-or-less ordinary local variables 
*inside* the class definition. Here's a working sketch of the sort of 
thing you can do. Copy and paste the following into a Python interactive 
session, and then see if you can follow what is being done when.


# === cut ===
import functools

def decorator_factory(a, b):
# This is a factory function that returns a decorator.
# First we do so pre-processing. This gets called only once (per 
# usage of the decorator).
value = a*10 + b - 1
print(precalculation of value = %s % value)
def decorator(func):
print(decorator called on method '%s' % func.__name__)
@functools.wraps(func)
def inner(self, fe, fi, fo):
return func(self, fe, fi, fo, fum=value)
return inner
# return the decorator
return decorator


class MyClass(object):
spam = 42
ham = 23
@decorator_factory(spam, ham)
def my_method(self, fe, fi, fo, fum):
print(fe, fi, fo, fum)


x = MyClass()
x.my_method(1, 2, 3)

# === end cut ==


Is 

Re: Decorator help

2013-03-27 Thread Jason Swails
On Wed, Mar 27, 2013 at 7:29 PM, Steven D'Aprano 
steve+comp.lang.pyt...@pearwood.info wrote:


 The one doesn't follow from the other. Writing decorators as classes is
 fairly unusual. Normally, they will be regular functions. If your
 decorator needs to store so much state that it needs to be a class,
 you're probably trying to do too much from a single decorator.

 There's more that you need to describe, such as what it is that the
 decorator actually does, and whether it does it once, when the decorator
 is called, or repeatedly, when the decorated method is called.

 The second case is the easiest. Suppose you have a class like this, with
 many methods which have code in common. Here's a toy example:


 def MyClass(object):
 x = class attribute

 def __init__(self, y):
 self.y = y


In the spirit of nit-picking, I'll point out that Steven meant to use the
'class' keyword instead of 'def' for MyClass.


 def MyClass(object):
 x = class attribute

 def __init__(self, y):
 self.y = y


And here as well.

It's potentially worth pointing out that this code will actually compile.
 It will even run, assuming you provide MyClass with a single argument.
 But it will always return None :).

As per usual, the response was thorough and helpful -- I appreciate
responses like these and how they've helped improve my command of Python.

All the best,
Jason
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Decorator help

2013-03-27 Thread Steven D'Aprano
On Wed, 27 Mar 2013 22:38:11 -0400, Jason Swails wrote:

 The second case is the easiest. Suppose you have a class like this,
 with many methods which have code in common. Here's a toy example:


 def MyClass(object):
 x = class attribute

 def __init__(self, y):
 self.y = y


 In the spirit of nit-picking, I'll point out that Steven meant to use
 the 'class' keyword instead of 'def' for MyClass.


/face-palm


So I did. Thanks for picking the nit.




-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list