Кто-нибудь использует мета-мета-классы / мета-мета-мета-классы в Python / других языках? - PullRequest
14 голосов
/ 24 января 2009

Я недавно открыл метаклассы в Python.

По сути, метакласс в python - это класс, который создает класс. Есть много полезных причин, по которым вы хотели бы сделать это - любой тип инициализации класса, например. Регистрация классов на фабриках, комплексная проверка атрибутов, изменение работы наследования и т. Д. Все это становится не только возможным, но и простым.

Но в python метаклассы также являются простыми классами. Итак, я начал задаваться вопросом, может ли абстракция с пользой пойти выше, и мне кажется, что она может и что:

  • метакласс соответствует или реализует роль в шаблоне (как в языках шаблонов GOF).
  • мета-метакласс - это сам образец (если мы позволим ему создавать кортежи классов, представляющих абстрактные роли, а не только один класс)
  • мета-мета-метакласс является фабрикой шаблонов , которая соответствует группировкам шаблонов GOF, например, Творческий, Структурный, Поведенческий. Фабрика, на которой вы можете описать случай проблемы определенного типа, и она даст вам набор классов, которые ее решат.
  • мета-мета-мета-метакласс (насколько я могу судить) - это фабрика фабрики образцов , фабрика, на которой вы, возможно, сможете описать тип вашей проблемы, и он даст вам фабрику образцов спросить.

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

Кто-нибудь еще использовал метаклассы, подобные этому, в python / elsewhere, или видел, как это используется в дикой природе, или думал об этом? Какие есть аналоги на других языках? Например. в C ++ насколько глубока может быть рекурсия шаблона?

Я бы очень хотел исследовать это дальше.

Ответы [ 5 ]

18 голосов
/ 25 января 2009

Это напоминает мне о вечном поиске, который некоторые люди, кажется, собираются сделать "общей реализацией шаблона". Как фабрика, которая может создать любой объект (, включая другую фабрику ), или универсальная структура внедрения зависимостей, которой гораздо сложнее управлять, чем просто написание кода, который на самом деле делает что-то.

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

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

В противном случае это просто черепахи внизу .

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

Во время конференции History of Programming Languages ​​в 2007 году Саймон Пейтон Джонс отметил, что Haskell разрешает метапрограммирование с использованием Type Classes, но на самом деле он все время рушится. Вы можете написать мета-мета-мета-мета и т. Д. На Haskell, но он никогда не слышал о том, чтобы кто-то использовал более 3 уровней косвенности.

Гай Стил указал, что в Lisp и Scheme то же самое. Вы можете заниматься метапрограммированием, используя обратные пометки и уловки (вы можете думать о обратном ударе как о лямбде Python, вроде бы), но он никогда не видел, чтобы использовалось более трех обратных ударов.

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

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

7 голосов
/ 24 января 2009

Чтобы ответить на ваш вопрос: нет.

Не стесняйтесь исследовать это дальше.

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

Хороший код часто отражает множество взаимосвязанных шаблонов проектирования. Там нет простого способа формализовать это. Лучшее, что вы можете сделать, - это хорошая картинка, хорошо написанные строки документов и имена методов, которые отражают различные шаблоны проектирования.

Также обратите внимание, что мета-класс - это класс. Это петля. Там нет более высокого уровня абстракций. На данный момент, это просто намерение. Идея мета-мета-класса не имеет большого значения - это мета-класс для мета-классов, что глупо, но технически возможно. Однако это всего лишь класс.


Редактировать

«Действительно ли классы, которые создают метаклассы, настолько глупы? Как внезапно заканчивается их полезность?»

Класс, который создает класс, в порядке. Вот и все. Тот факт, что целевой класс является мета-классом или абстрактным суперклассом или конкретным классом, не имеет значения. Метаклассы делают классы. Они могут создавать другие метаклассы, что странно, но они все еще просто создают классы метаклассов.

Утилита "внезапно" заканчивается, потому что в метаклассе, который создает другой метакласс, нет никакой реальной вещи, которая вам нужна (или даже может написать) Дело не в том, что это «внезапно» становится глупым. Там нет ничего полезного.

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

Цель ОО - написать определения классов, которые моделируют объекты реального мира. Как таковой, метакласс иногда удобен для определения сквозных аспектов нескольких связанных классов. (Это способ сделать некоторое Аспектно-ориентированное Программирование.) Это все, что может сделать метакласс; это место для хранения нескольких функций, таких как __new__(), которые не являются частями самого класса.

4 голосов
/ 25 января 2009

Система классов в Smalltalk интересна для изучения. В Smalltalk все является объектом, и у каждого объекта есть класс. Это не означает, что иерархия уходит в бесконечность. Если я правильно помню, это выглядит примерно так:

5 -> Целое число -> Целочисленный класс -> Метакласс -> Метакласс -> Метакласс -> ... (это циклы)

Где '->' обозначает "это экземпляр".

2 голосов
/ 25 августа 2017

С тех пор, как я впервые понял метаклассы в Python, я продолжал задаваться вопросом «что можно сделать с помощью мета-мета-класса?». Это было по крайней мере 10 лет назад - и теперь, всего пару месяцев назад, мне стало ясно, что существует один механизм создания классов Python, который на самом деле включает в себя класс «мета-мета». И, следовательно, можно попытаться представить себе какое-то использование для этого.

Чтобы повторить создание экземпляра объекта в Python: всякий раз, когда создается экземпляр объекта в Python, «вызывая» его класс с тем же синтаксисом, который используется для вызова обычной функции, __new__ и __init__ класса. То, что «управляет» вызовом этих методов в классе, это именно метод класса «метакласс» __call__. Обычно, когда пишут метакласс в Python, настраивается метод метакласса __new__ или __init__.

Итак, получается, что, написав класс «мета-мета», можно настроить его метод __call__ и, таким образом, контролировать, какие параметры передаются и метаклассам __new__ и __init__, а также, если некоторые другие код должен быть вызван до или после тех. В итоге получается, что сами меткалсы обычно жестко закодированы, и нужно всего несколько, если они вообще есть, даже в очень больших проектах. Поэтому любая настройка, которая может быть выполнена при вызове «meta meta», обычно выполняется непосредственно в самом метаклассе.

И они, есть и другие, менее часто используемые метаклассы Python - можно настроить метод __add__ в метаклассе так, чтобы определяемые ими классы были «добавляемыми», и создать производный класс, имеющий два добавленных класса как суперкласса. Этот механизм также отлично работает с метаклассами - поэтому, просто у нас «есть некоторый реальный код», следует пример класса «мета-мета», который позволяет составлять «метаклассы» для класса, просто добавляя их в объявление класса :

class MM(type):
    def __add__(cls, other):
        metacls = cls.__class__
        return metacls(cls.__name__ + other.__name__, (cls, other), {})

class M1(type, metaclass=MM):
    def __new__(metacls, name, bases, namespace):
        namespace["M1"] = "here"
        print("At M1 creation")
        return super().__new__(metacls, name, bases, namespace)

class M2(type, metaclass=MM):
    def __new__(metacls, name, bases, namespace):
        namespace["M2"] = "there"
        print("At M2 creation")
        return super().__new__(metacls, name, bases, namespace)

И мы видим, что работаем на интерактивной консоли:

In [22]: class Base(metaclass = M1 + M2): 
    ...:     pass
    ...: 
At M1 creation
At M2 creation

Обратите внимание, что поскольку разные метаклассы в Python, как правило, трудно комбинировать, это на самом деле может быть полезно, позволяя комбинировать метакласс, созданный пользователем, с библиотекой или классом stdlib, без необходимости явно объявлять его как родительский для класса. бывший:

In [23]: import abc

In [24]: class Combined(metaclass=M1 + abc.ABCMeta):
    ...:     pass
    ...: 
At M1 creation
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...