web-dev-qa-db-fra.com

Les types d'unions existent-ils réellement en python?

Puisque python est typé dynamiquement, nous pouvons bien sûr faire quelque chose comme ceci:

def f(x):
    return 2 if x else "s"

Mais est-ce la façon dont python était réellement destiné à être utilisé? Ou en d'autres termes, les types d'unions existent-ils dans le sens qu'ils font dans Racket par exemple? Ou les utilisons-nous uniquement comme ceci:

def f(x):
    if x:
        return "s"

où la seule "union" dont nous avons besoin est avec None?

13
Lana

La saisie par union n'est nécessaire que si vous disposez d'un langage typé statiquement, car vous devez déclarer qu'un objet peut renvoyer un type parmi plusieurs (dans votre cas, un int ou str, ou dans l'autre exemple str ou NoneType).

Python ne traite que des objets , il n'est donc jamais nécessaire de considérer les "types d'union". Python renvoient ce qu'elles renvoient, si le programmeur veut retourner différents types pour des résultats différents, alors c'est leur choix. Le choix est alors un choix d'architecture, et ne fait aucune différence pour le Python (il n'y a donc rien à "comparer" ici).

Python 3.5 introduit une norme pour la création d'indices de type facultatif , et cette norme comprend Union[...] et Optional[...] annotations.

19
Martijn Pieters

le type lui-même n'existe pas parce que Python est juste un langage typé dynamiquement, cependant, dans les versions plus récentes Python, Union Type est une option pour Type Hinting ,

from typing import Union,TypeVar

T = TypeVar('T')
def f(x: T) -> Union[str, None]:
    if x:
        return "x"

vous pouvez l'utiliser pour annoter votre code, permettant ainsi la vérification de la syntaxe au niveau IDE/Editor.

10
Sajuuk

Voici quelques options pour traiter les cas d'utilisation où vous avez besoin d'un type union/sum étiqueté en Python:

  • Enum + Tuples

    from enum import Enum
    Token = Enum('Token', ['Number', 'Operator', 'Identifier', 'Space', 'Expression'])
    
    (Token.Number, 42)                            # int type
    (Token.Operator, '+')                         # str type 1
    (Token.Identifier, 'foo')                     # str type 2
    (Token.Space, )                               # no data
    (Token.Expression, 'lambda', 'x', 'x+x')      # multiple data
    
  • isinstance

    if isinstance(token, int):
        # Number type
    if isinstance(token, str):
        # Identifier type
    
  • sumtypes module

Bien entendu, ces approches ont toutes leurs inconvénients.

2
Mateen Ulhaq

Ajout à la réponse @MartijnPieters:

Mais est-ce que la manière python était réellement destinée à être utilisée?

Renvoyer un type différent en fonction du paramètre n'est jamais une bonne pratique dans aucune langue. Cela rend les tests, la maintenance et l'extension du code vraiment difficiles et à mon humble avis est un anti-modèle (mais bien sûr parfois le mal nécessaire). Les résultats doivent au moins être liés via une interface commune.

La seule raison pour laquelle union a été introduite dans C est le gain de performances. Mais en Python vous n'avez pas ce gain de performances en raison de la nature dynamique du langage (comme Martijn l'a remarqué). En fait, l'introduction de union réduirait les performances puisque la taille de union est toujours la taille du plus grand membre. Ainsi Python n'aura jamais de type C union.

2
freakish