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

Что можно сделать с помощью метаклассов, которые не могут быть каким-либо другим способом?

Алекс Мартелли сказал, что есть задачи, которые не могут быть достигнуты без метаклассов здесь метаклассы Python против декораторов класса Я хотел бы знать, какие?

8 ответов


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

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

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

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


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

но по этой Программирование метакласса в Python они могут вам не понадобиться ( пока )

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

-- Python Гуру Тим Питерс!--9-->


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

то, что я чаще всего использую метаклассы,-это постобработка атрибутов класса во время создания класса. Например, установка 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()

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


Если вы ищете примеры использования механизма metaclass, вы можете прочитать исходный код Джанго.формы.

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


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

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


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

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


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

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

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


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