Опубликован: 22.12.2005 | Доступ: свободный | Студентов: 24085 / 1831 | Оценка: 4.18 / 3.71 | Длительность: 16:10:00
ISBN: 978-5-9556-0109-0
Лекция 4:

Объектно-ориентированное программирование

Метаклассы

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

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

Пример, в котором класс порождается динамически в функции-фабрике классов:

def cls_factory_f(func):
  class X(object):
    pass
  setattr(X, func.__name__, func)
  return X

Использование будет выглядеть так:

def my_method(self):
  print "self:", self

My_Class = cls_factory_f(my_method)
my_object = My_Class()
my_object.my_method()

В этом примере функция cls_factory_f() возвращает класс с единственным методом, в качестве которого используется функция, переданная ей как аргумент. От этого класса можно получить экземпляры, а затем у экземпляров - вызвать метод my_method.

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

В Python имеется класс type, который на деле является метаклассом. Вот как с помощью его конструктора можно создать класс:

def my_method(self):
  print "self:", self

My_Class = type('My_Class', (object,), {'my_method': my_method})

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

В результате получится класс, эквивалентный следующему:

class My_Class(object):
  def my_method(self):
    print "self:", self

Но самое интересное начинается при попытке составить собственный метакласс. Проще всего наследовать метакласс от метакласса type (пример взят из статьи Дэвида Мертца):

>>> class My_Type(type):
...  def __new__(cls, name, bases, dict):
...   print "Выделение памяти под класс", name
...   return type.__new__(cls, name, bases, dict)
...  def __init__(cls, name, bases, dict):
...   print "Инициализация класса", name
...   return super(My_Type, cls).__init__(cls, name, bases, dict)
...
>>> my = My_Type("X", (), {})
Выделение памяти под класс X
Инициализация класса X

В этом примере не происходит вмешательство в создание класса. Но в __new__() и __init__() имеется полный программный контроль над создаваемым классом в период выполнения.

Примечание:

Следует заметить, что в метаклассах принято называть первый аргумент методов не self, а cls, чтобы напомнить, что экземпляр, над которым работает программист, является не просто объектом, а классом.

Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Павел Ялганов
Павел Ялганов

Скажите экзамен тоже будет ввиде теста? или там будет какое то практическое интересное задание?