Этот быстрый совет дает краткий обзор того, что мы подразумеваем под метаклассом в Python, и показывает некоторые примеры концепции.
Прежде чем углубиться в эту статью, я должен отметить важный момент о классах в Python, который облегчает нам понимание концепции метаклассов.
Является ли класс объектом в Python ?!
Если вы использовали язык программирования, отличный от Python, концепция, которую вы поняли о классах, скорее всего, это способ создания новых объектов. Это также верно в Python, но Python делает еще один шаг вперед — классы также считаются объектами!
Итак, если вы создали следующий класс в Python:
1
2
|
class myClass(object):
pass
|
Это просто означает, что объект с именем myClass
был создан в памяти. Поскольку этот объект может создавать новые объекты, он считается классом . Это означает, что мы можем применять объектные операции к классам в Python, поскольку классы сами являются объектами.
Таким образом, мы можем выполнять операции над классами, такие как присвоение класса переменной, следующим образом:
1
2
|
class_object = myClass()
print class_object
|
Который возвращает:
1
|
<__main__.myClass object at 0x102623610>
|
Вы даже можете передать класс myClass
в качестве параметра методу следующим образом:
1
2
3
4
|
def class_object(object):
print object
class_object(myClass)
|
Который возвращает следующий вывод:
1
|
<class ‘__main__.myClass’>
|
В дополнение к другим операциям вы обычно можете наносить на объекты.
Метаклассы
Может быть, вы сталкивались с ключевым словом type
в Python? Скорее всего, вы использовали его для проверки типа какого-либо объекта, как показано в следующих примерах:
1
2
3
4
|
print type(‘abder’)
print type(100)
print type(100.0)
print type(int)
|
В этом случае вы получите следующий вывод:
1
2
3
4
|
<type ‘str’>
<type ‘int’>
<type ‘float’>
<type ‘type’>
|
Глядя на вывод, все кажется довольно ясным, пока вы не придете к типу type
. Чтобы увидеть, что это может означать, давайте вернемся к нашему классу, который мы определили в начале этой статьи:
1
2
|
class myClass(object):
pass
|
Теперь сделайте следующее:
1
|
print type(myClass)
|
Каков будет результат этого заявления? Это будет на удивление:
1
|
<type ‘type’>
|
Итак, мы можем заключить, что тип классов в Python — это type
!
Какова связь между type
и metaclass
? Ну, type
— это metaclass
, при условии, что metaclass
по умолчанию — это type
. Я знаю, что это может сбивать с толку, особенно тот type
может использоваться для возврата класса некоторого объекта, как показано выше, но это связано с обратной совместимостью в Python. Итак, если вы напишите:
1
|
print type(type)
|
Ты получишь:
1
|
<type ‘type’>
|
Это означает, что type
есть type
!
Термин metaclass
просто означает то, что используется для создания классов . Другими словами, это класс класса, что означает, что экземпляр класса в этом случае является классом. Таким образом, type
считается metaclass
так как экземпляр type
является классом.
Например, когда мы упомянули следующее утверждение выше:
1
|
class_object = myClass()
|
Это просто создает объект / экземпляр класса myClass
. Другими словами, мы использовали класс для создания объекта.
Точно так же, когда мы сделали следующее:
1
2
|
class myClass(object):
pass
|
metaclass
был использован для создания класса myClass
(который считается type
). Таким образом, как и объект, являющийся экземпляром класса, класс является экземпляром metaclass
.
Использование метакласса для создания класса
В этом разделе мы увидим, как мы можем использовать metaclass
для создания класса, а не использовать оператор class
как мы видели в учебнике по классам и объектам . Как мы видели выше, metaclass
по умолчанию — это type
. Таким образом, мы можем использовать следующую инструкцию для создания нового класса:
1
|
new_class = type(‘myClass’,(),{})
|
Если вы хотите упростить ситуацию, вы можете присвоить имя переменной тому же имени myClass
.
Словарь { }
здесь используется для определения атрибутов класса. Итак, имея следующее утверждение:
1
|
myClass = type(‘myClass’,(),{‘a’:True})
|
Похоже на:
1
2
|
class myClass(object):
a = True
|
Атрибут __metaclass__
Скажем, что мы создали класс myClass
следующим образом:
1
2
3
|
class myClass(object):
__metaclass__ = myMetaClass
pass
|
В этом случае создание класса будет происходить с использованием myMetaClass
вместо type
, как myMetaClass
ниже:
1
|
myClass = myMetaClass(className, bases, dictionary)
|
Создание и инициализация метакласса
Если вы хотите иметь контроль над тем, как вы создаете и инициализируете класс после его создания, вы можете просто использовать метакласс __new__
метод и __init__
конструктор, соответственно. Итак, когда вышеупомянутый myMetaClass
вызывается, это то, что будет происходить за кулисами:
1
2
|
myClass = myMetaClass.__new__(myMetaClass, name, bases, dictionary)
myMetaClass.__init__(myClass, name, bases, dictionary)
|
Я не хочу, чтобы этот краткий совет был длиннее, но, резюмируя, мы можем заключить, что metaclass
используется в Python для создания класса. То есть экземпляр metaclass
— это класс. Если вы хотите углубиться в метаклассы, вы можете проверить этот учебник .