Re: [Python-Dev] Dinamically set __call__ method

2014-11-13 Thread Fabio Zadrozny
On Thu, Nov 13, 2014 at 2:20 AM, Gregory Ewing greg.ew...@canterbury.ac.nz
wrote:

 Fabio Zadrozny wrote:

 can someone from python-dev give some background of why that's the way it
 is?


 It's because, with new-style classes, a class is also an
 instance (of class type or a subclass thereof). So
 without that rule, it would be ambiguous whether a dunder
 method applied to instances of a class or to the class
 itself.

  and if maybe it's something which python-dev would consider worth

 changing in the future -- not sure how much could break because of that
 though


 Something fairly fundamental that would break is classs
 instantiation! You instantiate a class by calling it, so if
 a(x) were implemented as a.__call__(x), and class C had
 a __call__ method, then C() would invoke that method
 instead of instantiating C.


Hi Gregory,

Thanks for the explanation -- it still does seem a bit surprising from an
end-user point of view, but it does make more sense now :)

Best Regards,

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-13 Thread Lie Ryan

On 05/11/14 06:15, Roberto Martínez wrote:


The thing with this is tricky. I need the change in the instance,

 not in the class, because I have multiple instances and all of
 them must have different implementations of __call__.

Why not just use functions with closure if that's what you need?

def a(one):
two = 'three'
def mycall(self):
nonlocal two
print 'NEW'
return mycall

Python functions are objects.


The workaround of calling a different method inside __call__

 is not valid for my case because I want to change the *signature*
 of the function also -for introspection reasons.

This seems like they should be two totally separate classes. If the 
signature is different, then it violates the substitution principle. If 
it violates substitution, then there is no reason why they should be of 
the same class.



This was my first approach, but it is not very informative to the user
and I prefer to have arguments with descriptive names. We have to change
__doc__ too, so this is not an ideal solution for me.

I tried to implement __getattribute__, but is not called either. :(



Or you can use an factory function:

def A(p):
def xcall(self):
return 'X'
def ycall(self):
return 'Y'

class _A(object):
__call__ = xcall if p == 'x' else ycall
return _A

 A('x')()(), A('y')()()
('X', 'Y')

or plain and simply just use inheritance if you want to pass an 
isinstance check:


class A(object):
def __call__(self):
print 'OLD'

class A1(A):
def __call__(self):
print 'NEW'

What exactly, are you trying to do?

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-12 Thread Fabio Zadrozny
On Tue, Nov 11, 2014 at 5:43 AM, Ian Kelly ian.g.ke...@gmail.com wrote:

 On Sat, Nov 8, 2014 at 3:31 PM, Gregory Ewing
 greg.ew...@canterbury.ac.nz wrote:
  (BTW, I'm actually surprised that this technique makes c callable.
  There must be more going on that just look up __call__ in the class
  object, because evaluating C.__call__ just returns the descriptor
  and doesn't invoking the descriptor mechanism.)

 But of course it doesn't just lookup C.__call__, because it has to
 bind the method to the instance before calling it, which means
 invoking the descriptor protocol. The actual lookup is more like:

 type(a).__dict__['__call__'].__get__(a, type(a))
 --
 https://mail.python.org/mailman/listinfo/python-list



As a reference, I recently found a blog post related to that:
http://lucumr.pocoo.org/2014/8/16/the-python-i-would-like-to-see/ (the
Slots part comments on that).

It does seem a bit counter-intuitive that this happens the way it does
though, so, can someone from python-dev give some background of why that's
the way it is? i.e.: instead of the approach which would seem simpler which
would do getattr(a, '__call__') instead of
type(a).__dict__['__call__'].__get__(a, type(a)) -- it seems to me it's
mostly because of historical reasons, but I'm really curious why is it so
(and if maybe it's something which python-dev would consider worth changing
in the future -- not sure how much could break because of that though).

Thanks and Best Regards,

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-12 Thread Ian Kelly
On Wed, Nov 12, 2014 at 8:33 AM, Fabio Zadrozny fabi...@gmail.com wrote:
 As a reference, I recently found a blog post related to that:
 http://lucumr.pocoo.org/2014/8/16/the-python-i-would-like-to-see/ (the Slots
 part comments on that).

 It does seem a bit counter-intuitive that this happens the way it does
 though, so, can someone from python-dev give some background of why that's
 the way it is? i.e.: instead of the approach which would seem simpler which
 would do getattr(a, '__call__') instead of
 type(a).__dict__['__call__'].__get__(a, type(a)) -- it seems to me it's
 mostly because of historical reasons, but I'm really curious why is it so
 (and if maybe it's something which python-dev would consider worth changing
 in the future -- not sure how much could break because of that though).

I'm not someone from python-dev, but I think it's done to keep the
look-up logic predictable and avoid having to call __getattribute__
and __getattr__ when looking up magic methods. For at least
__getattribute__ and __getattr__ themselves we *can't* invoke those
methods while trying to look them up, so there's a case to be made for
consistency in that this way we don't have to remember which magic
methods use __getattribute__ and which ones don't. Performance is also
part of it, since these methods tend to be invoked frequently.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Python-Dev] Dinamically set __call__ method

2014-11-12 Thread Gregory Ewing

Fabio Zadrozny wrote:
can someone from python-dev give some background of why 
that's the way it is?


It's because, with new-style classes, a class is also an
instance (of class type or a subclass thereof). So
without that rule, it would be ambiguous whether a dunder
method applied to instances of a class or to the class
itself.

 and if maybe it's something which python-dev would consider worth
changing in the future -- not sure how much could break because of that 
though


Something fairly fundamental that would break is classs
instantiation! You instantiate a class by calling it, so if
a(x) were implemented as a.__call__(x), and class C had
a __call__ method, then C() would invoke that method
instead of instantiating C.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-10 Thread Ian Kelly
On Sat, Nov 8, 2014 at 3:31 PM, Gregory Ewing
greg.ew...@canterbury.ac.nz wrote:
 (BTW, I'm actually surprised that this technique makes c callable.
 There must be more going on that just look up __call__ in the class
 object, because evaluating C.__call__ just returns the descriptor
 and doesn't invoking the descriptor mechanism.)

But of course it doesn't just lookup C.__call__, because it has to
bind the method to the instance before calling it, which means
invoking the descriptor protocol. The actual lookup is more like:

type(a).__dict__['__call__'].__get__(a, type(a))
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Python-Dev] Dinamically set __call__ method

2014-11-09 Thread Gregory Ewing

Ethan Furman wrote:
And the thing going on is the normal python behavior (in 
__getattribute__, I believe) of examining the returned attribute to see 
if it is a descriptor, and if so invoking it.


Only if you look it up through the instance, though.
Normally, if you look up an attribute on a class,
the descriptor protocol doesn't get triggered.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-09 Thread Steven D'Aprano
Gregory Ewing wrote:

 Ethan Furman wrote:
 And the thing going on is the normal python behavior (in
 __getattribute__, I believe) of examining the returned attribute to see
 if it is a descriptor, and if so invoking it.
 
 Only if you look it up through the instance, though.
 Normally, if you look up an attribute on a class,
 the descriptor protocol doesn't get triggered.

Since this whole thread is about giving instances their own individual
__call__ methods, I don't think that doing the look-up on the class is part
of the requirements :-)

This seems to work for me:



class call_instance(object):
def __get__(self, obj, cls=None):
if cls is None:  cls = type(obj)
if obj is None:  obj = cls
return obj.my_call

class SomeClass(object):
__call__ = call_instance()


a = SomeClass()
b = SomeClass()
c = SomeClass()
c.eggs = 23

from types import MethodType
a.my_call = lambda x, y=1: x/y
b.my_call = lambda spam: str(spam).upper()
c.my_call = MethodType(lambda self: self.eggs + 1, c)




-- 
Steven

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-09 Thread Ethan Furman

On 11/09/2014 03:38 AM, Gregory Ewing wrote:

Ethan Furman wrote:


And the thing going on is the normal python behavior (in __getattribute__, I 
believe) of examining the returned
attribute to see if it is a descriptor, and if so invoking it.


Only if you look it up through the instance, though.
Normally, if you look up an attribute on a class,
the descriptor protocol doesn't get triggered.


Hrmm, maybe we're not talking about the same thing.  I was responding to your 
comment:


(BTW, I'm actually surprised that this technique makes c callable.
There must be more going on that just look up __call__ in the class
object, because evaluating C.__call__ just returns the descriptor
and doesn't invoking the descriptor mechanism.)


which seems to clash with what you just said.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-08 Thread Ethan Furman

On 11/07/2014 10:50 PM, dieter wrote:

Ethan Furman et...@stoneleaf.us writes:


On 11/06/2014 10:59 PM, dieter wrote:

John Ladasky writes:

On Tuesday, November 4, 2014 11:12:31 AM UTC-8, Ethan Furman wrote:


If you really absolutely positively have to have the signature be correct for 
each instance, you may to either look at a
function creating factory, a class creating factory, or a meta-class.


+1.  Overriding __call__() within the class definition, over and over again, 
with different function, looks awkward to me.


A possibility to get the original approach implemented looks like:

make __call__ a descriptor on the class which looks up the real
method on the instance.


This still wouldn't get the signatrue correct, though.


Why not? Once the descriptor is resolved, you get the final
instance method - with the correct signature.


Hmmm... well, it wouldn't be correct on a class lookup, but, yeah, it would be correct for an instance lookup -- and 
maybe that's good enough for the OP.


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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-08 Thread Gregory Ewing

Ethan Furman wrote:



On 11/06/2014 10:59 PM, dieter wrote:


A possibility to get the original approach implemented looks like:

make __call__ a descriptor on the class which looks up the real
method on the instance.


This still wouldn't get the signatrue correct, though.


Why not? Once the descriptor is resolved, you get the final
instance method - with the correct signature.


Hmmm... well, it wouldn't be correct on a class lookup, but, yeah, it 
would be correct for an instance lookup -- and maybe that's good enough 
for the OP.


Seems to depend on how you get hold of the object you're
inspecting the signature of. I did an experiment:

  class C(object):

  @property
def __call__(self):
  return self.call

  def f(x, y):
print(Called f with %s, %s % (x, y))

  c = C()
  c.call = f
  c(17, 42)

prints:
  Called f with 17, 42

This works too:

  import inspect
  print(inspect.getargspec(c.__call__))

prints:
  ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=None)

But

  print(inspect.getargspec(c))

doesn't work:

  TypeError: __main__.C object at 0x479250 is not a Python function

(BTW, I'm actually surprised that this technique makes c callable.
There must be more going on that just look up __call__ in the class
object, because evaluating C.__call__ just returns the descriptor
and doesn't invoking the descriptor mechanism.)

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-08 Thread Ethan Furman

On 11/08/2014 02:31 PM, Gregory Ewing wrote:


Seems to depend on how you get hold of the object you're
inspecting the signature of. I did an experiment:

   class C(object):

   @property
 def __call__(self):
   return self.call

   def f(x, y):
 print(Called f with %s, %s % (x, y))

   c = C()
   c.call = f
   c(17, 42)

prints:
   Called f with 17, 42

This works too:

   import inspect
   print(inspect.getargspec(c.__call__))

prints:
   ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=None)

But

   print(inspect.getargspec(c))

doesn't work:

   TypeError: __main__.C object at 0x479250 is not a Python function

(BTW, I'm actually surprised that this technique makes c callable.
There must be more going on that just look up __call__ in the class
object, because evaluating C.__call__ just returns the descriptor
and doesn't invoking the descriptor mechanism.)


Looks like you found a bug in inspect.getargspec.

And the thing going on is the normal python behavior (in __getattribute__, I believe) of examining the returned 
attribute to see if it is a descriptor, and if so invoking it.


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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-07 Thread Ethan Furman

On 11/06/2014 10:59 PM, dieter wrote:

John Ladasky writes:

On Tuesday, November 4, 2014 11:12:31 AM UTC-8, Ethan Furman wrote:


If you really absolutely positively have to have the signature be correct for 
each instance, you may to either look at a
function creating factory, a class creating factory, or a meta-class.


+1.  Overriding __call__() within the class definition, over and over again, 
with different function, looks awkward to me.


A possibility to get the original approach implemented looks like:

   make __call__ a descriptor on the class which looks up the real
   method on the instance.


This still wouldn't get the signatrue correct, though.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-07 Thread dieter
Ethan Furman et...@stoneleaf.us writes:

 On 11/06/2014 10:59 PM, dieter wrote:
 John Ladasky writes:
 On Tuesday, November 4, 2014 11:12:31 AM UTC-8, Ethan Furman wrote:

 If you really absolutely positively have to have the signature be correct 
 for each instance, you may to either look at a
 function creating factory, a class creating factory, or a meta-class.

 +1.  Overriding __call__() within the class definition, over and over 
 again, with different function, looks awkward to me.

 A possibility to get the original approach implemented looks like:

make __call__ a descriptor on the class which looks up the real
method on the instance.

 This still wouldn't get the signatrue correct, though.

Why not? Once the descriptor is resolved, you get the final
instance method - with the correct signature.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-06 Thread John Ladasky
On Tuesday, November 4, 2014 11:12:31 AM UTC-8, Ethan Furman wrote:

 If you really absolutely positively have to have the signature be correct for 
 each instance, you may to either look at a 
 function creating factory, a class creating factory, or a meta-class.

+1.  Overriding __call__() within the class definition, over and over again, 
with different function, looks awkward to me.


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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-06 Thread Steven D'Aprano
Roberto Martínez wrote:

 Yikes, I didn't realize the difference in inheritance.
 
 The thing with this is tricky. I need the change in the instance, not in
 the class, because I have multiple instances and all of them must have
 different implementations of __call__.
 
 The workaround of calling a different method inside __call__ is not valid
 for my case because I want to change the *signature* of the function also
 -for introspection reasons.

This is somewhat of a code smell. It's a bit whiffy, which doesn't
*necessarily* mean it is off, only that it could be. You should think hard
about your use-case and consider alternative strategies.

Like, the strategy design pattern :-)

The real problem here is that the individual functions have different
signatures. If they had the same signature, then you could bake that into
the __call__ method and simply call a per-instance method:

class X:
# Variation on the strategy design pattern.
def __call__(self, spam, eggs=12):
method = getattr(self, 'my_custom_method', None)
if method is None:
# Default behaviour.
...
else:
return method(self, spam, eggs)

Then simply add a `my_custom_method` function to the individual instances.
The different functions would provide different algorithms
(implementations) for the same task, with the same interface. This is
exactly the problem with the Strategy design pattern is supposed to solve.

But the smelly part here is that your custom functions take different
signatures, which suggests that they aren't providing different algorithms
for the same task. Different signatures means that they are *not*
interchangeable, that they have different calling conventions and
presumably do different things:

# This only works in Python 2 with classic (old-style) classes
a, b, c = [X() for i in range(3)]
a.__call__ = lambda self: self.spam + 1
b.__call__ = lambda self, x, y: (self.eggs or x)*y
c.__call__ = lambda self, value: setattr(self, spam, value)

That's a strong violation of the expectation that any two instances of the
same class should be more or less interchangeable, with at most a few
exceptional cases (e.g. you can't swap the int instance 0 for the instance
2 in the expression x/2). But it's not *always* wrong, functions themselves
are all instances of FunctionType, and every instance does something
different when called. E.g. while you could swap math.sin for math.cos,
since both take the same parameters, you cannot swap math.sin for len.

Nevertheless, I urge you strongly to think hard about what problem you are
really trying to solve. Dynamically override __call__ is just a means to
an end. Perhaps there is something less magically you can do to solve the
problem? Is there some way to ensure that all the instances have the same
interface? This might be easy, given that they can store per-instance
state. If instance a needs an extra parameter that other instances don't,
perhaps it can take it from an instance attribute instead of an argument.



-- 
Steven

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-06 Thread dieter
John Ladasky john_lada...@sbcglobal.net writes:

 On Tuesday, November 4, 2014 11:12:31 AM UTC-8, Ethan Furman wrote:

 If you really absolutely positively have to have the signature be correct 
 for each instance, you may to either look at a 
 function creating factory, a class creating factory, or a meta-class.

 +1.  Overriding __call__() within the class definition, over and over again, 
 with different function, looks awkward to me.

A possibility to get the original approach implemented looks like:

  make __call__ a descriptor on the class which looks up the real
  method on the instance.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Ethan Furman

This list is for the development _of_ Python, not development _with_ Python.

Try asking on Python List.

(forwarding...)

On 11/04/2014 08:52 AM, Roberto Martínez wrote:


I am trying to replace dinamically the __call__ method of an object using 
setattr.
Example:

$ cat testcall.py
class A:
 def __init__(self):
 setattr(self, '__call__', self.newcall)

 def __call__(self):
 print(OLD)

 def newcall(self):
 print(NEW)

a=A()
a()

I expect to get NEW instead of OLD, but in Python 3.4 I get OLD.

$ python2.7 testcall.py
NEW
$ python3.4 testcall.py
OLD

I have a few questions:

- Is this an expected behavior?
- Is possible to replace __call__ dinamically in Python 3? How?


In 2.7 that would be a classic class, about which I know little.

In 3.x you have a new class, one which inherits from 'object'.  When you replace __call__ you need to replace it the 
class, not on the instance:


  setattr(__self__.__class__, self.newcall)

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Roberto Martínez
Yikes, I didn't realize the difference in inheritance.

The thing with this is tricky. I need the change in the instance, not in
the class, because I have multiple instances and all of them must have
different implementations of __call__.

The workaround of calling a different method inside __call__ is not valid
for my case because I want to change the *signature* of the function also
-for introspection reasons.

Thank you all.

Best regards,
Roberto

(Ethan, sorry for posting to python-dev, I thought that it was an
implementation detail of CPython 3.X)

On Tue, Nov 4, 2014 at 7:23 PM, Ethan Furman et...@stoneleaf.us wrote:

 This list is for the development _of_ Python, not development _with_
 Python.

 Try asking on Python List.

 (forwarding...)


 On 11/04/2014 08:52 AM, Roberto Martínez wrote:


 I am trying to replace dinamically the __call__ method of an object using
 setattr.
 Example:

 $ cat testcall.py
 class A:
  def __init__(self):
  setattr(self, '__call__', self.newcall)

  def __call__(self):
  print(OLD)

  def newcall(self):
  print(NEW)

 a=A()
 a()

 I expect to get NEW instead of OLD, but in Python 3.4 I get OLD.

 $ python2.7 testcall.py
 NEW
 $ python3.4 testcall.py
 OLD

 I have a few questions:

 - Is this an expected behavior?
 - Is possible to replace __call__ dinamically in Python 3? How?


 In 2.7 that would be a classic class, about which I know little.

 In 3.x you have a new class, one which inherits from 'object'.  When you
 replace __call__ you need to replace it the class, not on the instance:

   setattr(__self__.__class__, self.newcall)

 --
 ~Ethan~

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Skip Montanaro
On Tue, Nov 4, 2014 at 1:01 PM, Roberto Martínez robertomartin...@gmail.com
 wrote:

 The workaround of calling a different method inside __call__ is not valid
 for my case because I want to change the *signature* of the function also
 -for introspection reasons.


You could define __call__ like so:

def __call__(self, *args, **kwds):
self._my_call(*args, **kwds)

then set self._my_call at runtime.

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Ethan Furman

On 11/04/2014 11:01 AM, Roberto Martínez wrote:

Yikes, I didn't realize the difference in inheritance.

The thing with this is tricky. I need the change in the instance, not in the 
class, because I have multiple instances
and all of them must have different implementations of __call__.

The workaround of calling a different method inside __call__ is not valid for 
my case because I want to change the
*signature* of the function also -for introspection reasons.


If you really absolutely positively have to have the signature be correct for each instance, you may to either look at a 
function creating factory, a class creating factory, or a meta-class.  The first option may work if you don't need an 
actual class, both of the last two options will be creating different classes, probably with one instance each (unless 
you have several instances which could share the same __call__).


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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Ethan Furman

On 11/04/2014 11:01 AM, Roberto Martínez wrote:


(Ethan, sorry for posting to python-dev, I thought that it was an 
implementation detail of CPython 3.X)


No worries.  It's good practice to post here first, just in case.  ;)

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Roberto Martínez
On Tue, Nov 4, 2014 at 8:06 PM, Skip Montanaro skip.montan...@gmail.com
wrote:


 On Tue, Nov 4, 2014 at 1:01 PM, Roberto Martínez 
 robertomartin...@gmail.com wrote:

 The workaround of calling a different method inside __call__ is not valid
 for my case because I want to change the *signature* of the function also
 -for introspection reasons.


 You could define __call__ like so:

 def __call__(self, *args, **kwds):
 self._my_call(*args, **kwds)


This was my first approach, but it is not very informative to the user and
I prefer to have arguments with descriptive names. We have to change
__doc__ too, so this is not an ideal solution for me.

I tried to implement __getattribute__, but is not called either. :(

then set self._my_call at runtime.

 Skip


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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Nathaniel Smith
On Tue, Nov 4, 2014 at 7:15 PM, Roberto Martínez
robertomartin...@gmail.com wrote:


 On Tue, Nov 4, 2014 at 8:06 PM, Skip Montanaro skip.montan...@gmail.com
 wrote:


 On Tue, Nov 4, 2014 at 1:01 PM, Roberto Martínez
 robertomartin...@gmail.com wrote:

 The workaround of calling a different method inside __call__ is not valid
 for my case because I want to change the *signature* of the function also
 -for introspection reasons.


 You could define __call__ like so:

 def __call__(self, *args, **kwds):
 self._my_call(*args, **kwds)


 This was my first approach, but it is not very informative to the user and I
 prefer to have arguments with descriptive names. We have to change __doc__
 too, so this is not an ideal solution for me.

 I tried to implement __getattribute__, but is not called either. :(

I'd suggest starting a new thread on python-list (or stack overflow or
whatever) explaining what the heck you're trying to do here and asking
for higher-level advice/suggestions, because your current
implementation strategy seems to have placed you on a path that is
rapidly descending past spaghetti towards tentacular.

(Or alternatively I guess you could go all in: Iä! Iä! Metaclasses Fhtagn!)

-n

-- 
Nathaniel J. Smith
Postdoctoral researcher - Informatics - University of Edinburgh
http://vorpus.org
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread Ethan Furman

On 11/04/2014 11:23 AM, Nathaniel Smith wrote:


(Or alternatively I guess you could go all in: Iä! Iä! Metaclasses Fhtagn!)


Metaclasses aren't that bad!  I've written one.

And the dizzy spells are getting better!

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


Re: [Python-Dev] Dinamically set __call__ method

2014-11-04 Thread alex23

On 11/04/2014 08:52 AM, Roberto Martínez wrote:

I am trying to replace dinamically the __call__ method of an object
using setattr.
Example:

$ cat testcall.py
class A:
 def __init__(self):
 setattr(self, '__call__', self.newcall)

 def __call__(self):
 print(OLD)

 def newcall(self):
 print(NEW)

a=A()
a()

I expect to get NEW instead of OLD, but in Python 3.4 I get OLD.


Given that special methods can only be replaced on the class and not the 
instance, you could create a new version of the class within __init__ 
and assign it to the instance:


class A:
def __init__(self, call_method=None):
if call_method:
methods = {'__call__': call_method}
self.__class__ = type('Custom_A', (A,), )

def __call__(self):
return 'original'

 a = A()
 a()
old
 b = A(lambda self: 'new')
 b()
new
--
https://mail.python.org/mailman/listinfo/python-list