Je sais que cette __call__
méthode dans une classe est déclenchée lorsque l'instance d'une classe est appelée. Cependant, je ne sais pas quand je peux utiliser cette méthode spéciale, car on peut simplement créer une nouvelle méthode et effectuer la même opération effectuée dans __call__
method et au lieu d'appeler l'instance, vous pouvez appeler la méthode.
J'apprécierais vraiment que quelqu'un me donne une utilisation pratique de cette méthode spéciale.
python
methods
call
magic-methods
mohi666
la source
la source
__call__
est cachée à la vue; c'est ainsi que vous instanciez une classe:x = Foo()
est vraimentx = type(Foo).__call__(Foo)
, où__call__
est défini par la métaclasse deFoo
.Réponses:
Le module Django Forms utilise
__call__
bien la méthode pour implémenter une API cohérente pour la validation de formulaire. Vous pouvez écrire votre propre validateur pour un formulaire dans Django en tant que fonction.Django a des validateurs intégrés par défaut tels que des validateurs d'e-mails, des validateurs d'url, etc., qui relèvent généralement des validateurs RegEx. Pour les implémenter proprement, Django a recours à des classes appelables (au lieu de fonctions). Il implémente la logique de validation Regex par défaut dans un RegexValidator, puis étend ces classes pour d'autres validations.
Maintenant, votre fonction personnalisée et EmailValidator intégré peuvent être appelés avec la même syntaxe.
Comme vous pouvez le voir, cette implémentation dans Django est similaire à ce que d'autres ont expliqué dans leurs réponses ci-dessous. Cela peut-il être mis en œuvre d'une autre manière? Vous pourriez, mais à mon humble avis, ce ne sera pas aussi lisible ou aussi facilement extensible pour un gros framework comme Django.
la source
Cet exemple utilise la mémorisation , le stockage essentiellement des valeurs dans un tableau (dictionnaire dans ce cas) afin que vous puissiez les consulter plus tard au lieu de les recalcul.
Ici, nous utilisons une classe simple avec une
__call__
méthode pour calculer les factorielles (via un objet appelable ) au lieu d'une fonction factorielle qui contient une variable statique (ce qui n'est pas possible en Python).Vous avez maintenant un
fact
objet qui peut être appelé, comme toute autre fonction. Par exempleEt il est également avec état.
la source
fact
objet indexable puisque votre__call__
fonction est essentiellement un index. Utiliserait également une liste au lieu d'un dict, mais ce n'est que moi.__call__
, être simple et rien de plus.Je trouve cela utile car cela me permet de créer des API faciles à utiliser (vous avez un objet appelable qui nécessite des arguments spécifiques), et faciles à implémenter car vous pouvez utiliser des pratiques orientées objet.
Ce qui suit est le code que j'ai écrit hier qui crée une version des
hashlib.foo
méthodes qui hachent des fichiers entiers plutôt que des chaînes:Cette implémentation me permet d'utiliser les fonctions de la même manière que les
hashlib.foo
fonctions:Bien sûr, j'aurais pu l'implémenter d'une manière différente, mais dans ce cas, cela semblait être une approche simple.
la source
__call__
vous donne un outil qui vous permet d'utiliser des techniques OO pour résoudre des problèmes.isinstance
ou quelque chose de similaire.__call__
méthode au lieu d'une fermeture est lorsque vous avez affaire au module de multitraitement, qui utilise le décapage pour transmettre des informations entre les processus. Vous ne pouvez pas sélectionner une clôture, mais vous pouvez sélectionner une instance d'une classe.__call__
est également utilisé pour implémenter des classes de décorateur en python. Dans ce cas, l'instance de la classe est appelée lorsque la méthode avec le décorateur est appelée.la source
Oui, lorsque vous savez que vous avez affaire à des objets, il est parfaitement possible (et dans de nombreux cas conseillé) d'utiliser un appel de méthode explicite. Cependant, vous avez parfois affaire à du code qui attend des objets appelables - généralement des fonctions, mais grâce à
__call__
vous, vous pouvez créer des objets plus complexes, avec des données d'instance et plus de méthodes pour déléguer des tâches répétitives, etc. qui sont toujours appelables.De plus, vous utilisez parfois à la fois des objets pour des tâches complexes (où il est logique d'écrire une classe dédiée) et des objets pour des tâches simples (qui existent déjà dans des fonctions ou sont plus facilement écrites sous forme de fonctions). Pour avoir une interface commune, vous devez soit écrire de petites classes encapsulant ces fonctions avec l'interface attendue, soit conserver les fonctions des fonctions et rendre les objets plus complexes appelables. Prenons les threads comme exemple. Les
Thread
objets du module standard de la bibliothèquethreading
veulent un appelable commetarget
argument (c'est-à-dire comme action à faire dans le nouveau thread). Avec un objet appelable, vous n'êtes pas limité aux fonctions, vous pouvez également transmettre d'autres objets, comme un worker relativement complexe qui obtient des tâches à faire à partir d'autres threads et les exécute séquentiellement:Ce n'est qu'un exemple qui me vient à l'esprit, mais je pense que c'est déjà assez complexe pour justifier le cours. Faire cela uniquement avec des fonctions est difficile, au moins cela nécessite le retour de deux fonctions et cela devient lentement complexe. On pourrait renommer
__call__
quelque chose d'autre et passer une méthode liée, mais cela rend le code créant le thread un peu moins évident et n'ajoute aucune valeur.la source
__call__
utilisé des instances de classe (au lieu de fonctions) comme applications WSGI. Voici un exemple tiré de "The Definitive Guide to Pylons": Using Instances of ClassesLes décorateurs basés sur les classes utilisent
__call__
pour référencer la fonction encapsulée. Par exemple:Il y a une bonne description des différentes options ici sur Artima.com
la source
La
__call__
méthode et les fermetures IMHO nous donnent un moyen naturel de créer un modèle de conception STRATÉGIE en Python. Nous définissons une famille d'algorithmes, encapsulons chacun d'eux, les rendons interchangeables et à la fin nous pouvons exécuter un ensemble d'étapes communes et, par exemple, calculer un hachage pour un fichier.la source
Je viens de tomber sur une utilisation de
__call__()
concert avec__getattr__()
laquelle je trouve que c'est beau. Il vous permet de masquer plusieurs niveaux d'une API JSON / HTTP / (cependant_sérialisée) à l'intérieur d'un objet.La
__getattr__()
partie prend en charge le retour itératif d'une instance modifiée de la même classe, en remplissant un attribut supplémentaire à la fois. Ensuite, après que toutes les informations ont été épuisées,__call__()
prend le relais avec les arguments que vous avez transmis.En utilisant ce modèle, vous pouvez par exemple passer un appel comme
api.v2.volumes.ssd.update(size=20)
, qui se termine par une requête PUT àhttps://some.tld/api/v2/volumes/ssd/update
.Le code particulier est un pilote de stockage en bloc pour un certain backend de volume dans OpenStack, vous pouvez le vérifier ici: https://github.com/openstack/cinder/blob/master/cinder/volume/drivers/nexenta/jsonrpc.py
EDIT: mise à jour du lien pour pointer vers la révision principale.
la source
Spécifiez a
__metaclass__
et remplacez la__call__
méthode, et demandez à la méthode des méta-classes spécifiée de__new__
renvoyer une instance de la classe, alto vous avez une "fonction" avec des méthodes.la source
Nous pouvons utiliser
__call__
method pour utiliser d'autres méthodes de classe comme méthodes statiques.la source
Un exemple courant est le
__call__
infunctools.partial
, voici une version simplifiée (avec Python> = 3.5):Usage:
la source
L'opérateur d'appel de fonction.
La méthode __call__ peut être utilisée pour redéfinir / réinitialiser le même objet. Il facilite également l'utilisation des instances / objets d'une classe en tant que fonctions en passant des arguments aux objets.
la source
Je trouve un bon endroit pour utiliser des objets appelables, ceux qui définissent
__call__()
, est lors de l' utilisation des capacités de programmation fonctionnelle en Python, tels quemap()
,filter()
,reduce()
.Le meilleur moment pour utiliser un objet appelable sur une fonction simple ou une fonction lambda est lorsque la logique est complexe et doit conserver un état ou utilise d'autres informations qui ne sont pas transmises à la
__call__()
fonction.Voici un code qui filtre les noms de fichiers en fonction de leur extension de nom de fichier à l'aide d'un objet appelable et
filter()
.Appelable:
Usage:
Production:
la source
C'est trop tard mais je donne un exemple. Imaginez que vous ayez une
Vector
classe et unePoint
classe. Les deux prennentx, y
comme arguments positionnels. Imaginons que vous souhaitiez créer une fonction qui déplace le point à placer sur le vecteur.4 solutions
put_point_on_vec(point, vec)
Faites-en une méthode sur la classe vectorielle. par exemple
my_vec.put_point(point)
Point
classe.my_point.put_on_vec(vec)
Vector
implémente__call__
, vous pouvez donc l'utiliser commemy_vec_instance(point)
Cela fait en fait partie de quelques exemples sur lesquels je travaille pour un guide des méthodes dunder expliquées avec Maths que je vais publier tôt ou tard.
J'ai quitté la logique du déplacement du point lui-même car ce n'est pas le sujet de cette question
la source