J'ai découvert l'ellipsis operator de python (...
). Dans le contexte où je l'utilise, c'est équivalent à pass
, autrement dit ne rien faire. C'est utilisé principalement pour quand python attend qu'un bloc syntaxique soit rempli (corps d'une fonction, d'une boucle, …), mais qu'on a vraiment rien à y faire. Je trouve que ça permet de faire des interfaces plus élégantes.
from abc import ABC, abstractmethod
class CarElementVisitor(ABC):
@abstractmethod
def visitBody(self, element):
...
@abstractmethod
def visitEngine(self, element):
...
@abstractmethod
def visitWheel(self, element):
...
@abstractmethod
def visitCar(self, element):
...
plutôt que
from abc import ABC, abstractmethod
class CarElementVisitor(ABC):
@abstractmethod
def visitBody(self, element):
raise NotImplementedError
@abstractmethod
def visitEngine(self, element):
raise NotImplementedError
@abstractmethod
def visitWheel(self, element):
raise NotImplementedError
@abstractmethod
def visitCar(self, element):
raise NotImplementedError
La perte de l'exception n'est pas un problème car elle n'est de toute façon jamais lancé, abc
(Abstract Base Classes, module python ajoutant les notions de classes abstraites et d'interfaces s'occupant d'en lancer une automatiquement:
$ ipython
Python 3.10.6 (main, Aug 3 2022, 17:39:45) [GCC 12.1.1 20220730]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from abc import ABC, abstractmethod
...:
...: class CarElementVisitor(ABC):
...: @abstractmethod
...: def visitBody(self, element):
...: ...
...:
...: @abstractmethod
...: def visitEngine(self, element):
...: ...
...:
...: @abstractmethod
...: def visitWheel(self, element):
...: ...
...:
...: @abstractmethod
...: def visitCar(self, element):
...: ...
...:
In [2]: CarElementVisitor()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [2], in <cell line: 1>()
----> 1 CarElementVisitor()
TypeError: Can't instantiate abstract class CarElementVisitor with abstract methods visitBody, visitCar, visitEngine, visitWheel
# Docstring
Posté par jihele . Évalué à 5.
Merci, je connaissais pas.
Pour ces cas de figure, j'utilise souvent une docstring, ça suffit à faire plaisir à Python, pas besoin d'écrire pass, raise ou … et ça documente la méthode (en disant par exemple qu'il faut la surcharger et comment).
Un avantage de classes abstraites, c'est que l'exception pète à l'instanciation, pas à l'exécution de la méthode.
[^] # Re: Docstring
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 6.
Plutôt que
...
dans son exempleJe préfère de loin le
raise
…ou…ou alors le
pass
…et…et dans tous les cas la documentation aussi.
C'est vrai que si ça peut se suffire, c'est encore mieux. Merci pour le tuyau.
“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Docstring
Posté par jihele . Évalué à 4.
Oui, dans ce cas je préfère encore
Et il y a besoin de rien d'autre. (La coloration syntaxique a l'air de merder. Tant pis.)
# Autre usage de l'ellipsis
Posté par Meewan . Évalué à 4.
Ellipsis est aussi un objet. Ça peut être utile quand tu veux mette une valeur par défaut à une fonction qui peu prendre None en entrée.
Cette façon de faire est intéressante parce qu’en pratique ellipsis n'est jamais utilisé donc on aura pas de faux positif.
[^] # Re: Autre usage de l'ellipsis
Posté par Gil Cot ✔ (site web personnel, Mastodon) . Évalué à 6.
Intéressant… Mais je préfère quand même un
None
qui me semble plus lisible (là mon cerveau traduit anything ou juste etc. et c'est plus confusant.)“It is seldom that liberty of any kind is lost all at once.” ― David Hume
[^] # Re: Autre usage de l'ellipsis
Posté par Meewan . Évalué à 2.
Je préfère aussi
None
mais dans certains cas ce n'est pas une option car c'est une valeur acceptée en entrée qui est différente de la valeur par défaut. En pratique j’utilise très rarement...
comme valeur par défaut, c'est vraiment mon dernier recours.[^] # Re: Autre usage de l'ellipsis
Posté par jihele . Évalué à 5. Dernière modification le 16 septembre 2022 à 14:25.
Parfois, quand None est une valeur attendue, la lib utilise un singleton maison pour représenter l'absence de valeur. C'est le cas dans pandas, il me semble.
# Une autre utilisation d'Ellipsis
Posté par François GUÉRIN (Mastodon) . Évalué à 4.
Quand on souhaite annoter un tuple dont on ne connait pas la longueur a priori, on peut l'utiliser aussi…
Et je l'utilise aussi pour les classes abstraites ! (et j'abuse des annotations…)
[^] # Re: Une autre utilisation d'Ellipsis
Posté par paco81 . Évalué à 3.
Moi je connaissais dans le contexte numpy, où l'opérateur ellipsis est utilisé pour faire du "slicing". Par exemple, avec un tableau multidimensionnel A,
A[0,...]
signifie qu'on prend le premier élément de la première dimension, et tous les éléments des dimensions restantes. Ça équivaut par exemple àA[0,:,:,:]
pour un tableau à 4 dimensions, mais reste valable quel que soit le nombre de dimensions.# Surcharge
Posté par Spack . Évalué à 4. Dernière modification le 18 septembre 2022 à 21:46.
Cela permet aussi de déclarer plusieurs prototypes pour une fonction et ainsi mieux documenter les usages:
[^] # Re: Surcharge
Posté par jihele . Évalué à 3.
Dans ce cas-là, je pense qu'on met ce qu'on veut dans le corps de la fonction. On pourrait aussi mettre
pass
ou bien une docstring. Mais les exemples de @typing.overload utilisent en effet...
.# numpy
Posté par bayo . Évalué à 2.
Pour compléter, je pense que ça été créé pour
numpy
à la base. Mais j'ai pas trouvé de source.C'est bien connu des data scientists, pour accéder à des tableaux de données multidimensionnelles
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.