https://docs.python.org/3/reference/datamodel.html
By default, classes are constructed using 'type()'. The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace).
# Syntax.
# type(object) return the type of an object, like object.__class__ (one argument)
# type(name, bases, namespace) return a new type object (three arguments)
MyClass = type("MyClass", (), {}) # a dynamic form of the 'class' statement
# the same as
class MyClass:
pass
MyClass = type("MyClass", (BaseClass,), {'attribute' : 42})
# the same as
class MyClass(BaseClass):
attribute = 42
class Meta(type): # inheritence from 'type'
# __init__ is optional
def __new__(mcls, name, bases, namespace):
namespace['foo'] = 'Meta was here'
# 'foo' is added to the class namespace,
# before the class 'name' is created
cls = type.__new__(mcls, name, bases, namespace)
return cls
class C(metaclass=Meta):
pass
print(C.foo) # Meta was here
print(dir(C)) # 'foo' is here
print(C.__dict__['foo']) # Meta was here
models = {}
class ModelMetaclass(type):
def __new__(mcls, name, bases, namespace):
cls = type.__new__(mcls, name, bases, namespace)
models[name] = cls
return cls
class Model(metaclass=ModelMetaclass):
pass
class A(Model):
pass
class B(A):
pass
print(list(models)) # ['Model', 'A', 'B']