Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python inheritance, metaclasses and type() function

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!

like image 745
Zaur Nasibov Avatar asked Jan 07 '13 15:01

Zaur Nasibov


People also ask

Are metaclasses inherited Python?

Defining Metaclasses Principially, metaclasses are defined like any other Python class, but they are classes that inherit from "type". Another difference is, that a metaclass is called automatically, when the class statement using a metaclass ends.

Why would you use metaclasses in Python?

To create your own metaclass in Python you really just want to subclass type . A metaclass is most commonly used as a class-factory. When you create an object by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass.

What are metaclasses and when are they used in Python?

A metaclass in Python is a class of a class that defines how a class behaves. A class is itself an instance of a metaclass. A class in Python defines how the instance of the class will behave. In order to understand metaclasses well, one needs to have prior experience working with Python classes.

Is type a metaclass in Python?

type is a metaclass, of which classes are instances. Just as an ordinary object is an instance of a class, any new-style class in Python, and thus any class in Python 3, is an instance of the type metaclass.


1 Answers

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.

like image 93
nneonneo Avatar answered Oct 21 '22 05:10

nneonneo