pythoncallback

Writing a class that accepts a callback in Python?


I need to write a class that allows a subclass to set an attribute with the name of a function. That function must then be callable from instances of the class.

For example, I say I need to write a Fruit class where the subclass can pass in a welcome message. The Fruit class must expose an attribute print_callback that can be set.

class Fruit(object):
    print_callback = None

    def __init__(self, *args, **kwargs):
        super(Fruit, self).__init__(*args, **kwargs)
        self.print_callback("Message from Fruit: ")

I need to expose an API that is can be consumed by this code (to be clear, this code cannot change, say it is 3rd party code):

def apple_print(f):
    print "%sI am an Apple!" % f

class Apple(Fruit):
    print_callback = apple_print

If I run:

mac = Apple()

I want to get:

Message from Fruit: I am an Apple!

Instead I get:

TypeError: apple_print() takes exactly 1 argument (2 given)

I think this is because self is passed in as the first argument.

So how do I write the Fruit class? Thanks!


Solution

  • Python assumes that any functions bound within a class scope are methods. If you'd like to treat them as functions, you have to dig around in their attributes to retrieve the original function object:

    def __init__(self, *args, **kwargs):
        super(Fruit, self).__init__(*args, **kwargs)
    
        # The attribute name was changed in Python 3; pick whichever line matches
        # your Python version.
        callback = self.print_callback.im_func  # Python 2
        callback = self.print_callback.__func__ # Python 3
    
        callback("Message from Fruit: ")