Écrire une classe qui accepte un rappel en Python?

J'ai besoin d'écrire une classe qui permet à une sous-classe pour définir un attribut avec le nom d'une fonction. Cette fonction doit alors être appelées à partir d'instances de la classe.

Par exemple, je dis que j'ai besoin d'écrire un Fruit de la classe où la sous-classe peut transmettre un message de bienvenue. Le Fruit de la classe doit exposer un attribut print_callback qui peut être réglé.

class Fruit(object):
    print_callback = None

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

J'ai besoin d'exposer une API qui peut être consommé par ce code (pour être clair, ce code ne peut pas changer, dire que c'est la 3ème partie du code):

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

class Apple(Fruit):
    print_callback = apple_print

Si je lance:

mac = Apple()

Je veux obtenir:

Message de Fruit: je suis une Pomme!

Au lieu de cela j'obtiens:

TypeError: apple_print() prend exactement 1 argument (2)

Je pense que c'est parce que le moi est passé comme premier argument.

Alors, comment dois-je écrire le Fruit de la classe? Merci!

  • J'apprécie les problèmes que vous avez eu avec cette approche et les excellentes solutions ci-dessous. Cependant cela me semble que vous devriez être la définition de print_callback comme une méthode (peut-être juste appelé print_me, et d'obtenir des sous-classes pour le remplacer. Ce serait simple et pythonic. Pour chaque type différent de print_me méthode, une autre sous-classe.
  • Ma motivation pour poser la question que je voulais sous-classe de Google App Engine de google.appengine.ext.db.djangoforms (par exemple DF2) pour permettre de remplacer un attribut formfield_callback de la même manière que Django ModelForm (django.les formulaires.ModelForm). L'idée est que "la classe f(DF2)" pourrait ensuite être utilisé par les standards de Django, simplement en changeant la super-classe de django.les formulaires.ModelForm. Je ne sais pas pourquoi le Django auteurs ont défini formfield_callback comme un attribut.