Thanatos Thanatos - 5 months ago 31
Python Question

“Can't instantiate abstract class … with abstract methods” on class that shouldn't have any abstract method

Take the following minimal example:

import abc

class FooClass(object):
__metaclass__ = abc.ABCMeta

def FooMethod(self):
raise NotImplementedError()

def main():
derived_type = type('Derived', (FooClass,), {})

def BarOverride(self):
print 'Hello, world!'
derived_type.FooMethod = BarOverride

instance = derived_type()

gets you:

TypeError: Can't instantiate abstract class Derived with abstract methods FooMethod

(The exception occurs on the
instance = derived_type()

shouldn't be abstract: I've overridden it with
. So, why is this raising exceptions?

Disclaimer: Yes, I could use the explicit
syntax, and accomplish the exact same thing. (And even better, I can make it work!) But this is a minimal test case, and the larger example is dynamically creating classes. :-) And I'm curious as to why this doesn't work.

Edit: And to prevent the other obvious non-answer: I don't want to pass
in the third argument to
: In the real example,
needs to have
bound to it. It is easier to do this if I can define
after the creation of
. (If I can't do this, then why?)

Answer Source

Because the docs say so:

Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are not supported. The abstractmethod() only affects subclasses derived using regular inheritance; “virtual subclasses” registered with the ABC’s register() method are not affected.

A metaclass is only called when a class is defined. When abstractmethod has marked a class as abstract that status won't change later.