Question

I can't understand why the following code behaves a particular way, which is described below:

from abc import ABCMeta   

class PackageClass(object):
    __metaclass__ = ABCMeta        

class MyClass1(PackageClass):
    pass

MyClass2 = type('MyClass2', (PackageClass, ), {})

print MyClass1
print MyClass2

>>> <class '__main__.MyClass1'> 
>>> <class 'abc.MyClass2'>

Why does repr(MyClass2) says abc.MyClass2 (which is by the way not true)? Thank you!

Was it helpful?

Solution

The problem stems from the fact that ABCMeta overrides __new__ and calls its superclass constructor (type()) there. type() derives the __module__ for the new class from its calling context1; in this case, the type call appears to come from the abc module. Hence, the new class has __module__ set to abc (since type() has no way of knowing that the actual class construction took place in __main__).

The easy way around is to just set __module__ yourself after creating the type:

MyClass2 = type('MyClass2', (PackageClass, ), {})
MyClass2.__module__ = __name__

I would also recommend filing a bug report.

Related: Base metaclass overriding __new__ generates classes with a wrong __module__, Weird inheritance with metaclasses

1: type is a type object defined in C. Its new method uses the current global __name__ as the __module__, unless it calls a metaclass constructor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top