Язык программирования Python

       

Имитация типов


Для иллюстрации понятия полиморфизма можно построить собственный тип, похожий на встроенный тип "функция". Построить класс, объекты которого вызываются подобно методам или функциям, можно так:

class CountArgs(object): def __call__(self, *args, **kwargs): return len(args) + len(kwargs)

cc = CountArgs() print cc(1, 3, 4)

Как видно из этого примера, экземпляры класса CountArgs можно вызывать подобно функциям (в результате будет возвращено количество переданных параметров). При попытке вызова экземпляра на самом деле будет вызван метод __call__() со всеми аргументами.

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

class Point: def __init__(self, x, y): self.coord = (x, y) def __nonzero__(self): return self.coord[0] != 0 or self.coord[1] != 0 def __cmp__(self, p): return cmp(self.coord, p.coord)

for x in range(-3, 4): for y in range(-3, 4): if Point(x, y) < Point(y, x): print "*", elif Point(x, y): print ".", else: print "o", print

Программа выведет:

. * * * * * * . . * * * * * . . . * * * * . . . o * * * . . . . . * * . . . . . . * . . . . . . .

В данной программе класс Point (Точка) имеет метод __nonzero__(), который определяет истинностное значение объекта класса. Истину будут давать только точки, отличные от (0, 0). Другой метод - __cmp__() - вызывается при необходимости сравнить точку и другой объект (имеющий как и точка атрибут coord, который содержит кортеж как минимум из двух элементов). Нужно заметить, что вместо __cmp__ можно определить отдельные методы для операций сравнения: __lt__, __le__, __ne__, __eq__, __ge__, __gt__ (для <, <=, !=, ==, >=, > соответственно).

Достаточно легко имитировать и числовые типы. Класс, который пользуется удобством синтаксиса инфиксного +, можно определить так:

class Plussable: def __add__(self, x): ... def __radd__(self, x): ... def __iadd__(self, x): ...

Здесь метод __add__() вызывается, когда экземпляр класса Plussable стоит слева от сложения, __radd__() - если справа от сложения и метод слева от него не имеет метода __add__(). Метод __iadd__() нужен для реализации +=.



Содержание раздела