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