Для чего нужны метаклассы Python? - PullRequest
30 голосов
/ 05 января 2010

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

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

Ответы [ 8 ]

19 голосов
/ 05 января 2010

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

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

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

10 голосов
/ 05 января 2010

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

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

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

- Гуру Питона Тим Питерс

8 голосов
/ 05 января 2010

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

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

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

4 голосов
/ 05 января 2010

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

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

1 голос
/ 05 января 2010

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

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

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

1 голос
/ 05 января 2010

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

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

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

1 голос
/ 05 января 2010

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

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

0 голосов
/ 25 мая 2014

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

...