8.20 通过字符串调用对象方法¶

问题¶

你有一个字符串形�的方法�称,想通过它调用�个对象的对应方法。

解决方案¶

最简�的情况,�以使用 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)  # Calls p.distance(0, 0)

�外一�方法是使用 operator.methodcaller() ,例如:

import operator
operator.methodcaller('distance', 0, 0)(p)

当你需�通过相�的�数多次调用�个方法时,使用 operator.methodcaller 就很方便了。 比如你需�排�一系列的点,就�以这样�:

points = [
    Point(1, 2),
    Point(3, 0),
    Point(10, -3),
    Point(-5, -7),
    Point(-1, 8),
    Point(3, 2)
]
# Sort by distance from origin (0, 0)
points.sort(key=operator.methodcaller('distance', 0, 0))

讨论¶

调用一个方法实际上是两步独立�作,第一步是查找属性,第二步是函数调用。 因此,为了调用�个方法,你�以首先通过 getattr() �查找到这个属性,然��去以函数方�调用它��。

operator.methodcaller() 创建一个�调用对象,并�时�供所有必��数, 然�调用的时候�需�将实例对象传递给它��,比如:

>>> p = Point(3, 4)
>>> d = operator.methodcaller('distance', 0, 0)
>>> d(p)
5.0
>>>

通过方法�称字符串�调用方法通常出现在需�模拟 case 语�或实现访问者模�的时候。 �考下一�节获�更多高级例�。