Опубликован: 22.12.2005 | Доступ: свободный | Студентов: 16667 / 511 | Оценка: 4.18 / 3.71 | Длительность: 16:16: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, чтобы напомнить, что экземпляр, над которым работает программист, является не просто объектом, а классом.

Андрей Егоров
Андрей Егоров

def bin(n):

"""Цифры двоичного представления натурального числа """

if n == 0:

   return []

n, d = divmod(n, 2)

return bin(n) + [d]

print bin(69)

Что значит здесь return[] ? Возвращает список? Непонятно какой список? Откуда он? 

 

 

Асмик Гаряка
Асмик Гаряка

Почему при вычислении рейтинга не учитывается уровень, как описано? Для всех курсов У=1, хотя для Специалист должно быть 2.

Александр Воронцов
Александр Воронцов
Украина