98 votes

Comment annoter une fonction qui prend un tuple de longueur variable ? (annotation du type de tuple variadique)

J'ai une fonction qui prend un tuple de différentes longueurs comme argument :

from typing import Tuple

def process_tuple(t: Tuple[str]):
    # Do nasty tuple stuff

process_tuple(("a",))
process_tuple(("a", "b"))
process_tuple(("a", "b", "c"))

Lorsque j'annote la fonction comme indiqué ci-dessus, j'obtiens les messages d'erreur suivants

fool.py:9: error: Argument 1 to "process_tuple" has incompatible type "Tuple[str, str]"; expected "Tuple[str]"
fool.py:10: error: Argument 1 to "process_tuple" has incompatible type "Tuple[str, str, str]"; expected "Tuple[str]"

process_tuple fonctionne vraiment avec des tuples et je les utilise comme des listes immuables de longueur variable. Je n'ai pas trouvé de consensus sur ce sujet sur Internet, et je me demande donc comment je dois annoter ce type d'entrée.

0 votes

Obtenez-vous ces erreurs lorsque vous exécutez le code ? J'ai exécuté le code sans aucune erreur.

4 votes

J'obtiens ces erreurs quand je lance mypy .

176voto

Azat Ibrakov Points 3940

Nous pouvons annoter des tuples homogènes de longueur variable en utilisant la fonction ... littéral (alias Ellipsis ) comme ceci :

def process_tuple(t: Tuple[str, ...]):
    ...

Après cela, les erreurs devraient disparaître.

De la docs :

Pour spécifier un tuple de longueur variable de type homogène, utilisez le littéral ellipses, par exemple Tuple[int, ...] . Une plaine Tuple est équivalent à Tuple[Any, ...] et, à son tour, à tuple .

11 votes

En fait, ceci est un peu contre-intuitif et contre-logique. Si nous supposons que List[str] est acceptable pour les listes de longueur variable, alors pourquoi Tuple[str] n'est pas acceptable pour un tuple de longueur variable ? Et (type(("a", "a")) == type(("a", "a", "a")) donne True .

21 votes

@Montreal : c'est parce que tuple et list servent à des fins différentes : tuple sont des conteneurs hétérogènes (comme les arguments positionnels d'une fonction arbitraire ou un seul enregistrement de table du SGBDR, ou dans le monde des mathématiques - les éléments du produit cartésien de différents ensembles (ou une union de produits cartésiens), de sorte que chaque coordonnée peut avoir un type différent, mais leur nombre est généralement fixe), alors que list sont homogènes (comme une collection d'enregistrements de même table ou une séquence finie d'éléments d'un ensemble)

5 votes

@Montreal : donc Tuple[str] est un simple str -objet tuple alors que List[str] est une collection d'un nombre arbitraire de str objets

7voto

Wolph Points 28062

En plus de la réponse Ellipsis telle que postée par Azat, vous pourriez la rendre plus explicite en utilisant @typing.overload o typing.Union

from typing import Tuple

@overload
def process_tuple(t: Tuple[str]):
    # Do nasty tuple stuff

@overload
def process_tuple(t: Tuple[str, str]):
    ...

Ou avec l'Union :

from typing import Tuple, Union

def process_tuple(t: Union[Tuple[str], Tuple[str, str], Tuple[str, str, str]]):
    # Do nasty tuple stuff

2 votes

Je le savais, mais mes tuples peuvent être très longs, donc ce n'est pas une option. Quoi qu'il en soit, je vous remercie.

1 votes

Au fait overload doivent passer avant la mise en œuvre

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X