Question

I have a class A that is callable. I also have a subclass of A called B that I want to make not callable. It should raise the normal "not callable" TypeError when I try to call it.

class A():
    def __call__(self):
        print "I did it"

class B(A):
    def __call__(self):
        raise TypeError("'B' object is not callable")

As you can see, my solution right now is to raise a duplicate of the normal TypeError. This feels wrong, since I'm just copying the text of a standard python exception. It would be better (in my opinion) if there was a way to mark a subclass as not callable and then have python handle that attribute.

What is the best way to make class B not callable, given that it's a subclass of the callable class A?

Was it helpful?

Solution

You can override type creation with Python metaclasses. Here after object creation, I replace parent's __call__ method with another one throwing an exception:

>>> class A(object):
    def __call__(self):
        print 'Called !'


>>> class MetaNotCallable(type):
    @staticmethod
    def call_ex(*args, **kwargs):
            raise NotImplementedError()

    def __new__(mcs, name, bases, dict):
        obj = super(MetaNotCallable, mcs).__new__(mcs, name, bases, dict)
        obj.__call__ = MetaNotCallable.call_ex # Change method !
        return obj


>>> class B(A):
    __metaclass__ = MetaNotCallable


>>> a = A()
>>> a()
Called !
>>> b = B()
>>> b()

Traceback (most recent call last):
  File "<pyshell#131>", line 1, in <module>
    b()
  File "<pyshell#125>", line 4, in call_ex
    raise NotImplementedError()
NotImplementedError
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top