Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

Например, если вы хотите, чтобы объект класса X, из которого исходит "print X", "Time is now 8:46 am" (в 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 позволяет удалить избыточность.

Ответ 2

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

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

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

- Python Guru Тим Петерс

Ответ 3

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

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

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