Search code examples
pythonpolymorphismfunction-reference

Taking Python class method as a polymorphic function


Edit: this question is based on two mistakes: not originally yincluding self in methods and assuming unbounded methods would not exhibit polymorphism, but they do. I voted to close it.

I can take a method as a function-valued object in Python:

class A:
    def foo(self):
        return "Hi, I'm A.foo"

f = A.foo
a = A()
print(f(a))

produces Hi, I'm A.foo.

So far so good. However, f won't work for sub-classes:

class B(A):
    def foo(self):
        return "Hi, I'm B.foo"

f = A.foo
b = B()
f(b)

still produces Hi, I'm A.foo, whereas b.foo() produces Hi, I'm B.foo. In other words, polymorphism does not apply.

Question: is there a way to get a function-valued object in f so that f(x) == x.foo() whenever isinstance(x, A)?

In other words, how do I complete the snippet below for things to work?

class A:
    def foo(self):
        return "Hi, I'm A.foo"

class B(A):
    def foo(self):
        return "Hi, I'm B.foo"

f = <WHAT DO I PUT HERE?>
a = A()
b = B()
assert f(a) == a.foo()
assert f(b) == b.foo()

Solution

  • Your can pull the class name out like so:

    class A:
        def foo(self):
            return "Hi, I'm {}.foo".format(self.__class__.__name__)
    
    class B(A):
        def foo(self):
            return "Hi, I'm {}.foo".format(self.__class__.__name__)
    
    f = A.foo  # this could be A or B, doesn't matter
    a = A()
    b = B()
    assert f(a) == a.foo()
    assert f(b) == b.foo()
    

    Note that because B inherits from A, you don't even need the foo method there:

    class A:
        def foo(self):
            return "Hi, I'm {}.foo".format(self.__class__.__name__)
    
    class B(A):
        pass
    
    f = A.foo
    a = A()
    b = B()
    assert f(a) == a.foo()
    assert f(b) == b.foo()