26

I wrote code like this

>>> class a(object):
        def __init__(self):
            self.__call__ = lambda x:x

>>> b = a()

I expected that object of class a should be callable object but evidently it is not and I can't understand why.

>>> b()

Traceback (most recent call last):
    File "<pyshell#5>", line 1, in <module>
        b()
TypeError: 'a' object is not callable
>>> callable(b)
False

>>> hasattr(b,'__call__')
True
1
  • I'm trying to make some syntatic sugar. You can imagine making a dynamic function generator like this. class A: b = create_custom_function("AA") c = create_custom_function("BB") Commented Nov 23, 2009 at 2:37

3 Answers 3

21

Special methods are looked up on the type (e.g., class) of the object being operated on, not on the specific instance. Think about it: otherwise, if a class defines __call__ for example, when the class is called that __call__ should get called... what a disaster! But fortunately the special method is instead looked up on the class's type, AKA metaclass, and all is well ("legacy classes" had very irregular behavior in this, which is why we're all better off with the new-style ones -- which are the only ones left in Python 3).

So if you need "per-instance overriding" of special methods, you have to ensure the instance has its own unique class. That's very easy:

class a(object):
    def __init__(self):
        self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
        self.__class__.__call__ = lambda x:x

and you're there. Of course that would be silly in this case, as every instance ends up with just the same "so-called per-instance" (!) __call__, but it would be useful if you really needed overriding on a per-individual-instance basis.

Sign up to request clarification or add additional context in comments.

Comments

20

__call__ needs to be defined on the class, not the instance

class a(object):
    def __init__(self):
        pass

    def __call__(self):
        return self

(Using a def because PEP8 discourages named lambdas.)

If you need to have different behaviour for each instance you could do it like this

class a(object):
    def __init__(self):
        self.myfunc = lambda x:x

    def __call__(self):
        return self.myfunc(self)

1 Comment

What if I want to create distinct per-instance callable function in runtime? Can you give me a suggestible way for that? Thanks for your reply.
2

What about this? Define a base class AllowDynamicCall:

class AllowDynamicCall(object):
     def __call__(self, *args, **kwargs):
         return self._callfunc(self, *args, **kwargs)

And then subclass AllowDynamicCall:

class Example(AllowDynamicCall):
     def __init__(self):
         self._callfunc = lambda s: s

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.