Re: [Python-Dev] Dinamically set __call__ method
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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