É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 deprint_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.
Vous devez vous connecter pour publier un commentaire.
Python suppose que toutes les fonctions liées à l'intérieur d'une étendue de classe sont des méthodes. Si vous souhaitez les traiter comme des fonctions, vous avez à creuser autour de leurs attributs à récupérer la fonction d'origine de l'objet:
self
argument de la fonction de sorte qu'il peut agir comme une méthode normale.im_func
attribut de méthodes ai renommé__func__
en Python 3.x.Vous pouvez utiliser directement:
ou:
Dans le premier cas, vous obtiendrez un seul paramètre (la version originale). Dans la deuxième, vous allez recevoir deux paramètres, où le premier sera la classe sur laquelle il a été appelé.
Espère que cette aide, et est plus court et moins complexe.
Mis à jour: l'intégration de abourget la suggestion de à utiliser
staticmethod
:Essayez ceci:
Je cherchais quelque chose de plus de ce genre quand j'ai trouvé cette question:
Il y a aussi un peu dirtyer solution avec les metaclasses:
Elle manipule la classe avant sa création!