Thanatos Thanatos - 9 months ago 55
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

@abc.abstractmethod
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()


Running
main()
gets you:

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


(The exception occurs on the
instance = derived_type()
line.)

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

Disclaimer: Yes, I could use the explicit
class
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
BarOverride
in the third argument to
type
: In the real example,
BarOverride
needs to have
derived_type
bound to it. It is easier to do this if I can define
BarOverride
after the creation of
derived_type
. (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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download