На этом шаге мы рассмотрим использование getattr() и operator.methodcaller().
У вас есть имя метода, хранящееся в виде строки, и вы хотите вызывать этот метод.
В простых случаях вы можете использовать getattr():
>>> import math >>> class Point: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return 'Point({!r:},{!r:})'.format(self.x, self.y) def distance(self, x, y): return math.hypot(self.x - x, self.y - y) >>> p = Point(2, 3) >>> d = getattr(p, 'distance')(0, 0) # Вызов p.distance(0, 0) >>>
Альтернативный подход - использование operator.methodcaller(). Например:
>>> import operator >>> operator.methodcaller('distance', 0, 0)(p) 3.6055512754639896 >>>
operator.methodcaller() может оказаться полезным, если вы хотите искать метод по имени и раз за разом предоставлять одни и те же аргументы. Например, если вам нужно отсортировать целый список точек:
>>> points = [
Point(1, 2),
Point(3, 0),
Point(10, -3),
Point(-5, -7),
Point(-1, 8),
Point(3, 2)
]
>>> # Сортируем по расстоянию от (0, 0)
>>> points.sort(key=operator.methodcaller('distance', 0, 0))
>>> for p in points:
print(p)
Point(1,2)
Point(3,0)
Point(3,2)
Point(-1,8)
Point(-5,-7)
Point(10,-3)
>>>
Вызов метода на самом деле состоит из двух отдельных шагов: поиска атрибута и вызова функции. Чтобы вызвать метод, вы просто ищете атрибут, используя getattr(), как и для любого другого атрибута. Чтобы вызывать результат как метод, просто обращайтесь с результатом поиска как с функцией.
operator.methodcaller() создает вызываемый объект, а также фиксирует аргументы, которые будут предоставлены методу. Вам остается только предоставить подходящий аргумент self. Например:
>>> p = Point(3, 4) >>> d = operator.methodcaller('distance', 0, 0) >>> d(p) 5.0 >>>
Вызов методов с использованием имен, содержащихся в строках, является обычным в коде, который эмулирует объявления условий, или вариантах паттерна (шаблона проектирования) "Посетитель". См. следующий рецепт, где приведен более продвинутый пример.
На следующем шаге мы рассмотрим реализацию шаблона проектирования "Посетитель".