Введение в язык Питон


Метаклассы: решение, требующее проблемы? - часть 2


У потомков type есть одно свойство, которое необходимо учитывать; на нем ловятся все, кто впервые использует метаклассы. Первый аргумент в методах обычно называется cls, а не self, поскольку эти методы обрабатывают созданный класс, а не метакласс. На самом деле, в этом нет ничего особенного; все методы связываются со своимиэкземплярами, а экземпляр метакласса является классом. Неспециальное имя делает это более очевидным:



Листинг 5. Прикрепление методов класса к созданным классам

>>> class Printable(type): ... def whoami(cls): print "I am a", cls.__name__ ... >>> Foo = Printable('Foo',(),{}) >>> Foo.whoami() I am a Foo >>> Printable.whoami() Traceback (most recent call last): TypeError: unbound method whoami() [...]

Вся эта удивительно непримечательная технология сопровождается некими синтаксическими украшениями, упрощающими работу с метаклассами и одновременно запутывающими новых пользователей. В этом дополнительном синтаксисе есть несколько элементов. Порядок интерпретации этих новых вариаций мудреный. Классы могут наследовать метаклассы от своих предков - заметьте, что это не одно и то же, что наличие метаклассов в качестве предков (еще одно обычное заблуждение). Для классов старого стиля определение глобальной переменной __metaclass__ приводит к использованию метаклассса, определенного пользователем. Однако по большей части самый безопасный подход - задать атрибут класса __metaclass__ для класса, который хочет быть созданным по метаклассу, определенному пользователем. Вы должны задать эту переменную в самом определении класса, поскольку метакласс не используется, если этот атрибут задан позднее (после того как объект класса уже был создан). Например:



Листинг 6. Задание метакласса с атрибутом класса

>>> class Bar: ... __metaclass__ = Printable ... def foomethod(self): print 'foo' ... >>> Bar.whoami() I am a Bar >>> Bar().foomethod() foo




Начало  Назад  Вперед



Книжный магазин