В этой статье объясняется, что такое метакласс в языке программирования Python и как добавить атрибуты в метакласс Python. Во-первых, давайте разберемся, что такое метакласс. Это достаточно продвинутая тема Python, и ожидаются следующие предварительные условия.
- Вы хорошо разбираетесь в концепциях Python OOP.
- Вы знакомы с языком программирования Python.
Чтобы понять метаклассы, вам нужно понять классы Python. В большинстве языков класс — это просто план, описывающий, как создаются объекты. В Python классы — это гораздо больше. Мало того, что классы определяют, как создаются экземпляры, классы Python сами по себе являются объектами. Поскольку классы являются объектами в Python, они являются экземплярами специального класса, называемого метаклассом, и все метаклассы являются экземплярами класса типов, которые создают эти объекты класса. Класс Type — это метакласс по умолчанию, отвечающий за создание классов. Проще говоря, объекты Python — это экземпляры класса, а классы — экземпляры метакласса. Следующая диаграмма резюмирует эту идею.
Когда использовать метакласс
- Если класс определен, а метакласс не определен, используется метакласс типа по умолчанию. Если метакласс указан, то базовый класс не является экземпляром type(), он будет использоваться непосредственно как тип для базового класса.
- Если вы хотите, чтобы ваш класс автоматически менялся при создании, используйте метакласс.
Ниже приведена простая демонстрация того, как атрибуты могут быть определены и добавлены в метакласс в Python.
Создание метакласса
Чтобы добавить атрибуты в метакласс в Python, сначала нам нужно создать метакласс, в Python мы создаем метакласс так же, как обычный класс, который наследует класс типа. Здесь создается метакласс с именем DemoMetaClass, который наследует класс типа, как показано ниже:
- __new__(): метод, вызываемый перед __init__(). Создает и возвращает объект.
- cls: относится к классу, в котором вызывается __new__.
- name: Обратитесь к имени класса.
- base: это родительский класс данного класса.
- defcl:определяет некоторые определения для класса.
Python3
class
DemoMetaClass(
type
):
attr1
=
1
def
__new__(
cls
, name, base, defcl):
obj
=
super
().__new__(
cls
, name, base, defcl)
obj.attr2
=
2
return
obj
Добавление атрибутов в созданный метакласс
Теперь, когда мы создали метакласс с именем DemoMetaClass и определили атрибуты attr1 и atrr2 при его определении, давайте создадим базовый класс, являющийся экземпляром этого метакласса. Как видите, мы создали 2 класса: первый — это класс Student по умолчанию, а второй — Demo с метаклассом DemoMetaCLass.
Python3
# Default Class
class
Student():
pass
# Base class inherited DemoMetaClass metaclass
class
Demo(metaclass
=
DemoMetaClass):
pass
(
"Student class is instance of "
,
type
(Student))
(
"Demo class is instance of "
, shamtype(Demo), end
=
"\n\n"
)
(f
"DemoMetaClass \nattr1 => {Demo.attr1} \nattr2 => {Demo.attr2}\n"
)
Вывод:
На изображении ниже показано, что по умолчанию метакласс является классом типов, как в случае класса Student, в то время как в случае Demo метаклассом является DemoMetaClass. Поскольку Demo является базовым классом DemoMetaClass, он также обладает атрибутами своего метакласса, который печатается на выходе.
Добавление нового атрибута
Мы также можем добавить атрибуты в метакласс, как мы это делаем с обычным классом в Python. Как вы можете видеть в выводе выше, в DemoMetaClass добавлен новый атрибут с именем attr3 со значением 3.
Python3
# Adding a new attribute attr3 to DemoMetaClass
DemoMetaClass.attr3
=
3
(
f"DemoMetaClass \nattr1
=
> {Demo.attr1} \nattr2
=
> {
Demo.attr2}\nattr3
=
> {Demo.attr3}")
Вывод:
Полный код
Python3
# Custom MetaClass Defined for demo
class
DemoMetaClass(
type
):
attr1
=
1
def
__new__(
cls
, name, base, defcl):
obj
=
super
().__new__(
cls
, name, base, defcl)
obj.attr2
=
2
return
obj
# Default Class
class
Student():
pass
# Base class inherited DemoMetaClass metaclass
class
Demo(metaclass
=
DemoMetaClass):
pass
(
"Student class is instance of "
,
type
(Student))
(
"Demo class is instance of "
,
type
(Demo), end
=
"\n\n"
)
(f
"DemoMetaClass \nattr1 => {Demo.attr1} \nattr2 => {Demo.attr2}\n"
)
# Adding a new attribute attr3 to DemoMetaClass
DemoMetaClass.attr3
=
3
(
f
"DemoMetaClass \nattr1 => {Demo.attr1} \nattr2 => {Demo.attr2}\nattr3 => {Demo.attr3}"
)
Вывод:
Student class is instance of <class 'type'> Demo class is instance of <class '__main__.DemoMetaClass'> DemoMetaClass attr1 => 1 attr2 => 2 DemoMetaClass attr1 => 1 attr2 => 2 attr3 => 3