Comme souligné dans les commentaires, l'union est probablement la meilleure approche. Si la signature semble désordonnée, vous pouvez utiliser type aliases comme ceci:
from typing import Tuple, Union
MyType = Union[Tuple[int, int], Tuple[int, int, int]]
def example1(i):
# type: (int) -> MyType
...snip...
Une autre approche serait d'utiliser le "indefinite length" Tuple type. Vous abandonneriez fondamentalement l'encodage de la longueur exacte du tuple mais en échange vous pouvez normaliser le type de retour et éviter cette union. (Si votre code fait compter sur la longueur, ce n'est probablement pas la meilleure approche). Toutefois, une approche un peu plus radicale consisterait à envisager une restructuration de votre code pour éviter ce type de situation.
Après tout, si vous renvoyez ces deux types distincts, l'appelant de votre fonction aura probablement besoin de vérifier la longueur de toute façon, non?
Dans ce cas, une idée est de renoncer à retourner un tuple et de retourner à la place un NamedTuple ou une classe personnalisée, les deux ayant un champ facultatif. Vous pouvez ensuite convertir votre chèque "longueur" en un chèque "est ce champ défini sur Aucun".
Je suppose que, dans un sens, l'approche NamedTuple répond également à votre demande initiale, tant que cela ne vous dérange pas de convertir vos Tuples/le surcoût ajouté.
from typing import NamedTuple, Optional
MyType2 = NamedTuple('MyType2', (
('x', int),
('y', int),
('z', Optional[int]),
))
class MyType3(object):
def __init__(self, x, y, z):
# type: (int, int, Optional[int]) -> None
self.x = x
self.y = y
self.z = z
(L'approche « de classe personnalisée » sera probablement plus élégante une fois PEP 557 est accepté et intégré dans la langue).
L'autre approche consiste à diviser votre fonction en deux si vous connaissez à l'avance le type de ligne que vous attendez. Ensuite, vous pouvez simplement appeler la fonction de ce type approprié.
Ce sont 2 types distincts. L'union est probablement la plus logique. – Carcigenicate