Для чего нужны метаклассы Python?

Для тех, кто использует anaconda Python:

conda update anaconda
30
задан Community 23 May 2017 в 12:17
поделиться

7 ответов

Метаклассы незаменимы, если вы хотите, чтобы объекты классов (в отличие от instances объектов классов) были оснащены "специальным настраиваемым поведением", так как поведение объекта зависит от специальных методов от типа объекта, а тип объекта класса является, именно, синонимом метакласса.

Например, если вы хотите, чтобы объект класса X, например, "print X" излучал "Time is now 8:46am" (в 8:46 утра, или, более широко, текущее время), это должно означать, что type(x) (метакласс AKA X) имеет специальный пользовательский метод __str__ -- и подобным образом (с различными применимыми специальными методами). если вы хотите придать значение таким выражениям, как X + Y, где X и Y являются объектами класса, или X[23] (где X, опять же, является объектом класса) и т.д.

Большинство других задач настройки теперь (на Python 2.6 или лучше) проще реализовать с помощью декоратора класса, который может изменить объект класса сразу после окончания оператора -класса . Есть еще несколько случаев, когда это неосуществимо, так как изменения должны быть сделаны очень рано, если они должны иметь какой-то эффект (например, установка или изменение __слотов__).

На Python 3 метаклассы получают одну дополнительную небольшую пользу: теперь метаклас может опционально указать объект отображения, который будет заполнен во время выполнения тела оператора class (по умолчанию это нормальный dict). Это позволяет сохранить и использовать порядок привязки имен в теле класса (в то время как обычный dict теряет порядок), что иногда приятно, когда класс должен иметь "поля" в определённом определённом порядке (например отобразить 1:1 на структуру C -, строку в CSV-файле или таблице БД, и тому подобное) -- на Python 2.* это должно было быть указано избыточно (обычно с дополнительным атрибутом класса, который является последовательностью и, таким образом, сохраняет порядок), и эта особенность Python 3 метакласса позволяет удалить избыточность.

19
ответ дан 28 November 2019 в 00:07
поделиться

Я использую метаклассы с некоторой частотой, и они являются чрезвычайно мощным инструментом. Иногда ваше решение проблемы может быть более элегантным, меньше кода, с ними, чем без них.

Чаще всего я использую метаклассы, это постобработка атрибутов класса во время создания класса. Например, установка атрибута name на объекты, где это уместно (например, как может работать Django ORM):

class AutonamingType(type):
    def __init__(cls, name, bases, attrs):
        for k,v in attrs.iteritems():
            if getattr(v, '__autoname__', False):
                v.name = k

class Autonamer(object):
    __metaclass__ = AutonamingType

Если у вас это в качестве инструмента, и вы используете класс, который должен знать свое name, прежде чем он сможет do_something():

class Foo(object):
    __autoname__ = True
    def __init__(self, name=None):
        self.name = name
    def do_something(self):
        if self.name is None:
            raise ValueError('name is None')
        # now, do something

В остальном ваш код может различаться между этим:

class Bar(object):
    myfoo1 = Foo('myfoo1')
    myfoo2 = Foo('myfoo2')
    myfoo3 = Foo('myfoo3')

и этим:

class Baaz(Autonamer):
    myfoo1 = Foo()
    myfoo2 = Foo()
    myfoo3 = Foo()

, уменьшая таким образом дублирование (и вероятность того, что имя переменной и присваиваемое имя могут выйти из синхронизации).

.
8
ответ дан 28 November 2019 в 00:07
поделиться

Если вы ищете примеры использования механизма метакласса, то можете ознакомиться с исходным кодом django.forms.

Декларативный стиль определения формы реализован через метакласс.

.
4
ответ дан 28 November 2019 в 00:07
поделиться

Взгляните на исходники Django - например, там для генерации моделей используются метаклассы.

http://code.djangoproject.com/wiki/DynamicModels

Внутри Django использует метаклассы, чтобы создавать модели на основе класса вы предоставить в вашем исходном коде. Без вдаваясь в слишком много деталей, что означает, что вместо твоих занятий будучи настоящими моделями, Джанго получает описание вашего класса, который он использует для создания модели в своей place.

1
ответ дан 28 November 2019 в 00:07
поделиться

Вероятно, нет ничего, что можно было бы сделать исключительно с метаклассами, но для некоторых людей (в том числе и для меня) это интересный инструмент, который можно использовать. Просто будьте осторожны, не злоупотребляйте, т.к. это может быть хитро.

Например, я использовал метапрограммирование в одном из недавних проектов. Это был лист калькуляции OpenOffice, который, используя некоторые макросы pyUNO, генерирует некоторые файлы с информацией. Был один лист, который представляет пользователю информацию, которую нужно заполнить, а другие можно использовать для описания типа элементов и их свойств. Затем пользователь может выбрать количество элементов и тип каждого из них и сгенерировать файлы. Макрос создаст класс с помощью метапрограммирования в соответствии с конфигурацией на каждом листе. Затем пользователь может инстанцировать каждый класс и генерировать объекты.

Это можно сделать и без метапрограммирования, но мне показалось естественным использовать для этого возможности метапрограммирования.

.
1
ответ дан 28 November 2019 в 00:07
поделиться

Они редко нужны, но бывают полезны там, где вы хотите добавить поведение к основному поведению объекта -- сравните Aspect Oriented Programming, или инструменты, выполненные в фреймворках персистентности, таких как Hibernate.

Например, вам может понадобиться класс, который сохраняет или регистрирует каждый новый объект.

.
1
ответ дан 28 November 2019 в 00:07
поделиться

Добавьте дополнительную гибкость в программировании:

Но согласно этому программирование на Python, возможно, вам не понадобится ( пока )

Метаклассы - это более глубокое волшебство, чем 99% пользователей, о которых стоит беспокоиться. Если вы задаётесь вопросом, нужны ли они вам, то нет (люди, которые действительно нуждаются в них, знают с уверенностью, что они нуждаются в них, и не нуждаются в объяснении почему)

-- Python Guru Tim Peters

10
ответ дан 28 November 2019 в 00:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: