Экземпляры создаются специальными объектами, называемыми «классами». Это означает, что классы также являются объектами и могут быть изменены, как мы изменяем экземпляры, с той лишь разницей, что если мы изменяем класс, это влияет на все экземпляры, созданные из класса.

>>> class Foo:
>>>     pass
>>> firstFoo = Foo()
>>> Foo.bar = 1
>>> print(firstFoo.bar)
1
>>> secondFoo = Foo()
>>> print(secondFoo.bar)
1
>>> secondFoo.a = 1
>>> print(secondFoo.a)
1
>>> print(firstFoo.a)
AttributeError: Foo instance has no attribute 'a'

Если экземпляры создаются классами, классы создаются специальными объектами, называемыми «метаклассами». Метапрограммирование - это изменение способа создания классов с помощью метаклассов.

Как?

Метакласс по умолчанию --type, и он обычно используется для создания классов, которые вы пишете.

class Foo:
    pass

такой же как:

Foo = type('Foo', (), {})

а также

>>> class B(list):
>>>     x = 1

>>>     def hi(self, name):
>>>         print('hi', name)
>>> def hii(self, name):
>>>     print('hi', name)
>>> def fake_init(self):
>>>     print('Fake init')
>>> C = type('C', (list,), {'x': 1, 'hii': hii, '__init__': fake_init})
>>> b = B()
1
>>> b.append(1)
>>> print(b.x)
1
>>> b.hi('B')
('hi', 'B')
>>> c = C()
Fake init
>>> c.append(1)
>>> print(c.x)
1
>>> c.hii('C')
('hi', 'C')

В приведенном выше коде показано, как мы можем использовать метакласс (в данном случае «тип») для создания классов. Метапрограммирование работает, добавляя ваши собственные операции к созданию классов, создавая подкласс метакласса type и вставляя его в процесс создания классов с помощью «ловушки метакласса».

В Python 3 ловушка метакласса - это аргумент ключевого слова metaclass в списке базовых классов определения класса. Если вы передадите класс в качестве аргумента ключевого слова в списке базовых классов в определении вашего класса, class B(metaclass=MyMetaClass): python вызовет его после первоначального создания класса, передав объект класса, имя класса, список базовых классов и словарь пространства имен.

>>> def custom_func(self):
>>>     print('Yeeehaaa')
>>> class MyMetaClass(type):
>>>     def __init__(cls, name, base_classes, namespace):
>>>         super(MyMetaClass, cls).__init__(name, base_classes, namespace)
>>>         cls.custom_func = custom_func
>>> class FooBar(metaclass=MyMetaClass):
>>>     pass
>>> bar = FooBar()
>>> bar.custom_func()
Yeeehaaa

Это основы метапрограммирования. Спасибо за прочтение :)

Ссылка: https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Metaprogramming.html