"""
You have the name of a method you that want to call on an object stored
as a string and you want to execute the method.
"""
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)


def main():
    p = Point(2, 3)

    # Method 1 : Use getattr
    d = getattr(p, "distance")(0, 0)  # Calls p.distance(0, 0)
    print(d)

    # Method 2: Use methodcaller
    import operator

    d = operator.methodcaller("distance", 0, 0)(p)
    print(d)

    # Application in sorting
    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))
    for p in points:
        print(p)


if __name__ == "__main__":
    main()
