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!
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: ")