Если статический метод имеет свои аналоги в C++ и Java, то метод класса основан на том, что в Python классы являются объектами. В отличие от статического метода, в метод класса первым параметром передается объект–класс. Вместо self
для подчеркивания принадлежности метода к методам класса принято использовать cls
.
Пример использования метода класса можно найти в модуле tree
пакета nltk
(Natural Language ToolKit, набор инструментов для естественного языка). Ниже приведен лишь фрагмент определения класса Tree
(базового класса для других подклассов). Метод convert
класса Tree
определяет процедуру преобразования дерева одного типа в дерево другого типа. Эта процедура абстрагируется от деталей реализации конкретных типов, описывая обобщенный алгоритм преобразования:
class Tree:
# ...
def convert(cls, val):
if isinstance(val, Tree):
children = [cls.convert(child) for child in val]
return cls(val.node, children)
else:
return val
convert = classmethod(convert)
Пример использования (взят из строки документации метода convert()
):
>>> # Преобразовать tree в экземпляр класса Tree
>>> tree = Tree.convert(tree)
>>> # " " " " " ParentedTree
>>> tree = ParentedTree.convert(tree)
>>> # " " " " " MultiParentedTree
>>> tree = MultiParentedTree.convert(tree)
Метод класса позволяет более естественно описывать действия, которые связаны в основном с классами, а не с методами экземпляра класса.
Метаклассы
Еще одним отношением между классами является отношение класс–метакласс. Метакласс можно считать «высшим пилотажем» объектно–ориентированного программирования, но, к счастью, в 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__()
имеется полный программный контроль над создаваемым классом в период выполнения.