Re: Decorating one method of a class C with another method of class C?

2014-06-08 Thread Dan Stromberg
On 6/6/14, Ben Finney b...@benfinney.id.au wrote:
 Dan Stromberg drsali...@gmail.com writes:

 Is there a way of decorating method1 of class C using method2 of class
 C?

 Can you give a concrete example (i.e. not merely hypothetical) where
 this would be a useful feature (i.e. an actual improvement over the
 absence of the feature), and why?

I have a class that's operating on a socket.

I'd like to have simple operations on that socket like list
configured hosts, allow connection to host, etc.  And I'd like them
to be decorated with reconnected_to_server_if_needed.

I'll probably end up putting a try/except in each simple operation,
making them a bit less simple.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Decorating one method of a class C with another method of class C?

2014-06-08 Thread Chris Angelico
On Mon, Jun 9, 2014 at 4:04 AM, Dan Stromberg drsali...@gmail.com wrote:
 I have a class that's operating on a socket.

 I'd like to have simple operations on that socket like list
 configured hosts, allow connection to host, etc.  And I'd like them
 to be decorated with reconnected_to_server_if_needed.

 I'll probably end up putting a try/except in each simple operation,
 making them a bit less simple.

Can you have the decorator outside the class, calling a regular method
to do its main work?

def recon_if_needed(f):
def inner(self, *a, **kw):
if self.disconnected: self.connect()
return f(self, *a, **kw)
return inner
class SocketWorker:
@recon_if_needed
def send_packet(self, packet):
assert not self.disconnected

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Decorating one method of a class C with another method of class C?

2014-06-08 Thread Ben Finney
Dan Stromberg drsali...@gmail.com writes:

 I'd like to have simple operations on that socket like list
 configured hosts, allow connection to host, etc. And I'd like them
 to be decorated with reconnected_to_server_if_needed.

The ‘reconnected_to_server_if_needed’ method, if I understand
your original post correctly, does not need the class nor the class
instance. So you can define that function outside the class, and use it
for decorating methods within the class.

-- 
 \ “Teach a man to make fire, and he will be warm for a day. Set a |
  `\   man on fire, and he will be warm for the rest of his life.” |
_o__) —John A. Hrastar |
Ben Finney

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


Decorating one method of a class C with another method of class C?

2014-06-06 Thread Dan Stromberg
Is there a way of decorating method1 of class C using method2 of class C?

It seems like there's a chicken-and-the-egg problem; the class doesn't
seem to know what self is until later in execution so there's
apparently no way to specify @self.method2 when def'ing method1.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Decorating one method of a class C with another method of class C?

2014-06-06 Thread Chris Angelico
On Sat, Jun 7, 2014 at 10:14 AM, Dan Stromberg drsali...@gmail.com wrote:
 Is there a way of decorating method1 of class C using method2 of class C?

 It seems like there's a chicken-and-the-egg problem; the class doesn't
 seem to know what self is until later in execution so there's
 apparently no way to specify @self.method2 when def'ing method1.

Since decoration happens at class creation, and arguments like self
are available only when the method's actually called, no, there's no
way you can define the method with something using information that
doesn't exist yet and may change from one call to the next :)

What are you trying to do, exactly?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Decorating one method of a class C with another method of class C?

2014-06-06 Thread Ben Finney
Dan Stromberg drsali...@gmail.com writes:

 Is there a way of decorating method1 of class C using method2 of class
 C?

Can you give a concrete example (i.e. not merely hypothetical) where
this would be a useful feature (i.e. an actual improvement over the
absence of the feature), and why?

 It seems like there's a chicken-and-the-egg problem; the class doesn't
 seem to know what self is until later in execution so there's
 apparently no way to specify @self.method2 when def'ing method1.

You're referring specifically to instance methods, it seems. Right,
there's no instance *of* the class during the *definition* of the class,
so ‘self’ can't refer to such an instance.

Also, an instance method needs to get the instance as the first
parameter, whereas the decorator must accept the to-be-decorated
function as its argument.

So I don't see what you're trying to achieve, rather than the more
straightforward and clearer use of a decorator function which *isn't* a
method in the same class.

Can you show a Simple, Self-Contained Complete Example to show us what
you're trying to do? More importantly, why you think it should be done
this way?

-- 
 \“Visitors are expected to complain at the office between the |
  `\ hours of 9 and 11 a.m. daily.” —hotel, Athens |
_o__)  |
Ben Finney

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


Re: Decorating one method of a class C with another method of class C?

2014-06-06 Thread Terry Reedy

On 6/6/2014 8:14 PM, Dan Stromberg wrote:

Is there a way of decorating method1 of class C using method2 of class C?

It seems like there's a chicken-and-the-egg problem; the class doesn't
seem to know what self is until later in execution so there's
apparently no way to specify @self.method2 when def'ing method1.


Class code is executed in a new local namespace, which later becomes the 
class attribute space. So you can (sort of), but I cannot see a reason 
to do so.


class C:
def deco(f):
print('decorating')
def inner(self):
print('f called')
return f(self)
return inner

@deco
def f(self):
print(self)

del deco  # because it is not really a method
# but rather an undecorated static method

c = C()
c.f()

decorating
f called
__main__.C object at 0x0348B898

If deco is decorated as a staticmethod, it has to be called on the class 
or an instance thereof after the class is constructed. If deco is 
defined outside the class, it can be used both inside and outside.


--
Terry Jan Reedy

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


Re: Decorating one method of a class C with another method of class C?

2014-06-06 Thread Steven D'Aprano
On Fri, 06 Jun 2014 17:14:54 -0700, Dan Stromberg wrote:

 Is there a way of decorating method1 of class C using method2 of class
 C?

Yes. See below.

 It seems like there's a chicken-and-the-egg problem; the class doesn't
 seem to know what self is until later in execution so there's
 apparently no way to specify @self.method2 when def'ing method1.

Directly inside the class statement, you don't need self. The class 
defines a namespace, like inside a function or globals, so you can just 
refer to names directly, like this:


class Spam:
def decorate(func):  # Look Ma, no self!
@functools.wraps(func)
def inner(self, *args):
print(self, args)
return func(*args)
return inner
@decorate
def method(self, a, b):
return a+b


That works fine for what you want to do. The disadvantage, however, is 
that if you call the decorate method from *outside* of the class scope 
(that is, from the outside like Spam.decorate, or inside a method like 
self.decorate) you'll run into some weird problems. Try it and see if you 
can diagnose the cause of the problem.


This problem has a trivial, simple, obvious and wrong solution: ensure 
that the decorate method is a static method. That requires Spam to be a 
new-style class (inherit from object, or a built-in), but is otherwise 
trivial:

class Spam(object):
@staticmethod
def decorate(func):  # Look Ma, no self!
...


Unfortunately, this does not work! staticmethod objects are not callable. 
It is only after you go through the descriptor protocol that you end up 
with something which is callable. Sad but true. That means that this will 
fail:

class Spam(object):
@staticmethod
def decorate(func): ...

@decorate  # calling directly fails
def method(self, args): ...


but this will be okay:

@Spam.decorate  # calling via Spam or instance works
def function(args): ...


We're *so close* it hurts :-(

Good news! staticmethod is a class, and like most classes we can subclass 
it and get the behaviour we want!

# Untested
class callablestaticmethod(staticmethod):
def __call__(self, *args):
return self.__func__(*args)

ought to do it. Then just use callablestaticmethod instead of 
staticmethod, and all will be ginger-peachy.


But what happens if you want the decorator to refer to the class itself? 
You can always hard-code references to Spam inside the decorate method, 
but a better solution may be to use a callableclassmethod instead. (Left 
as an exercise.)

Inside the decorated method, or the wrapper method inner, we can refer 
to self as normal, and such references won't be evaluated until call-
time when self exists. It's only inside the decorator itself, and the 
body of the class, that self doesn't yet exist.



-- 
Steven D'Aprano
http://import-that.dreamwidth.org/
-- 
https://mail.python.org/mailman/listinfo/python-list