IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Typage pour utilisation ultérieure


Sujet :

Python

  1. #1
    Membre averti

    Profil pro
    Enseignant
    Inscrit en
    Juillet 2003
    Messages
    296
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2003
    Messages : 296
    Points : 441
    Points
    441
    Par défaut Typage pour utilisation ultérieure
    Bonjour,
    Je cherche à éclaircir un point sombre de Python. En utilisant le typage des variables, comment puis-je typer une variable sans l’initialiser au préalable ?

    Dans l’exemple ci-dessous, ma propriété active_user est sensé être un User, mais elle s’initialisera plus tard dans l’exécution du programme.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MainApp:
        """
        Main App class
        """
     
        def __init__(self):
            """
            Constructor
            """
            self.users: dict[User, Vault] = {}
            self.active_user: User = None
            #…
    Je pourrais mettre Optional[User] en typage, mais dans ce cas, PyLance ronchonne sur la suite du code, car il ne peut pas être possible d’avoir None.

    Je pourrais aussi utiliser des assert, mais j’en suis pas fan.

    Y a-t-il une piste que je puisse creuser ?

    Merci,

    Bonne journée !

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 048
    Points : 1 378
    Points
    1 378
    Par défaut
    Et Ellipsis à la place de None ?

  3. #3
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Bizarre cette notion de typage chez Python, parce qu'il n'y a aucun contrôle: c'est l'affectation qui détermine le type,et non la déclaration de type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    a:int = 0.5
    type(a)
    float
    Et donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    b:int = None
    type(b)
    NoneType
    Conclusion: est-on vraiment sûr que ça apporte quelque chose?
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  4. #4
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Citation Envoyé par Raylemon Voir le message
    Bonjour,
    Je cherche à éclaircir un point sombre de Python. En utilisant le typage des variables, comment puis-je typer une variable sans l’initialiser au préalable ?

    Dans l’exemple ci-dessous, ma propriété active_user est sensé être un User, mais elle s’initialisera plus tard dans l’exécution du programme.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MainApp:
        """
        Main App class
        """
     
        def __init__(self):
            """
            Constructor
            """
            self.users: dict[User, Vault] = {}
            self.active_user: User = None
            #…
    Je pourrais mettre Optional[User] en typage, mais dans ce cas, PyLance ronchonne sur la suite du code, car il ne peut pas être possible d’avoir None.

    Je pourrais aussi utiliser des assert, mais j’en suis pas fan.

    Y a-t-il une piste que je puisse creuser ?

    Merci,

    Bonne journée !
    On peut typer sans initialiser sans aucun soucis.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mon_integer: int
    ma_string: str
    mon_instance_de_classe_toto: Toto
    Et si un attribut ou une variable peuvent être de plusieurs types différents (au choix) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mon_int_ou_ma_string: int | str
    toto: int | str | None

  5. #5
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Hello,

    @tyrtamos,


    Faire du typing sans vérificateur de types, ça ne sert à rien ! Je te propose de regarder du côté de MyPy, C'est un outil qui vérifie si les données que j'utilise dans mon code Python sont correctes. C'est super utile pour éviter les erreurs et pour s'assurer que mon code fonctionne comme je le souhaite.

    Supposons que tu veuilles écrire une fonction qui prend deux nombres en entrée et renvoie leur somme. Avec Mypy, tu peux définir le type des entrées, par exemple entiers, pour s'assurer que les entrées sont bien des nombres entiers. Si quelqu'un appelle cette fonction avec des entrées qui ne sont pas des entiers, Mypy le signalera lors de la vérification du type, ce qui te permettra de corriger le problème avant même d'exécuter le code.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Citation Envoyé par Arioch Voir le message
    On peut typer sans initialiser sans aucun soucis.
    Ce serait logique, mais après la déclaration de typage, la variable n'existe toujours pas (elle n'a donc pas de type!), et elle n'existera qu'à la 1ère affectation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    e:int
    type(e)
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    ----> 1 type(e)
    NameError: name 'e' is not defined


    Citation Envoyé par Arioch Voir le message
    Et si un attribut ou une variable peuvent être de plusieurs types différents (au choix) :
    Chez moi, ça ne marche pas:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    toto: int | str
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    ----> 1 toto: int | str
    TypeError: unsupported operand type(s) for |: 'type' and 'type'
    Je suis sous Python 3.9: est-ce que ça s'arrange avec un Python plus récent?
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  7. #7
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Python 3.9.16 (main, Jan  7 2023, 22:12:13) [GCC 11.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> toto: int | str
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for |: 'type' and 'type'
    >>> 
    >>> 
    >>> from typing import Union
    >>> 
    >>> toto: Union[int, str]
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  8. #8
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je suis sous Python 3.9: est-ce que ça s'arrange avec un Python plus récent?
    En effet. C'est arrivé avec la 3.10.

    A l'époque de la 3.9 et des versions antérieures, j'utilisais le module typing et j'importais Optional

    Pour faire ceci :

    Je faisais alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    from typing import Optional
     
    toto: Optional[int, str]

  9. #9
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    après la déclaration de typage, la variable n'existe toujours pas (elle n'a donc pas de type!)
    J'utilise VsCode au quotidien, boulot ou perso.

    Typer ses attributs ou variables permet d'avoir rapidement une alerte si on affecte une valeur qui est d'un typage différent de celui déclaré.

    Comme le mentionne fred1599 un peu plus haut, si on se gourre sur ce point, mypy ne sera pas content et l'indiquera clairement.

    Et si, comme moi, tu es habitué à bosser sur le même fichier en parallèle avec tes collègues, tu es bien content d'avoir le typage, et eux aussi.

    "Ah mais c'est un int qu'il faut renvoyer ? Bordel, j'étais parti sur une chaîne moi !"
    "J'ai pourtant bien mis le bon typage, na !"

    Et c'est pratique pour les docstrings où, si tu énumères les arguments en E/S, bah t'as pas besoin de spécifier le typage dans ce que tu mets en commentaires.

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def classifications(self, keywords: str, labels: list[str]) -> list[dict[str, str | list[str]]]:
            '''Method Description.
            groups keywords and labels in a list.
            
            Args:
                keywords: the keywords.
                labels: list of different labels.
            
            Returns:
                list of two dicts with keywords and labels values.
            '''

  10. #10
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Je faisais alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    from typing import Optional
     
    toto: Optional[int, str]
    Optional permet de définir un type spécifique ou None, ce n'est pas ce que je comprends dans toto: int | str car on ne parle pas de l'option possible None non plus.

    D'ailleurs on peut faire un test rapide

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    >>> from typing import Optional
    >>> toto: Optional[int, str]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python3.9/typing.py", line 277, in inner
        return func(*args, **kwds)
      File "/usr/local/lib/python3.9/typing.py", line 354, in __getitem__
        return self._getitem(self, parameters)
      File "/usr/local/lib/python3.9/typing.py", line 478, in Optional
        arg = _type_check(parameters, f"{self} requires a single type.")
      File "/usr/local/lib/python3.9/typing.py", line 166, in _type_check
        raise TypeError(f"{msg} Got {arg!r:.100}.")
    TypeError: typing.Optional requires a single type. Got (<class 'int'>, <class 'str'>).
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  11. #11
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Ceci fonctionne :

    En Python <3.10, j'aurais fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    toto: Optional[int, str, None]
    Et quand tu ne sais pas trop ce que tu vas coller dans ta variable ou ton attribut, au bout d'un moment, moi hein...


  12. #12
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Citation Envoyé par Arioch Voir le message
    Ceci fonctionne :

    En Python <3.10, j'aurais fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    toto: Optional[int, str, None]
    Bah non !

    voir ma réponse précédente !
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  13. #13
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    My bad.

    Bon, ça fait un moment que je bosse en 3.10. Me souviens plus exactement comment je faisais.

  14. #14
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Citation Envoyé par Arioch Voir le message
    My bad.

    Bon, ça fait un moment que je bosse en 3.10. Me souviens plus exactement comment je faisais.
    Sans doute avec le mot clé Union comme indiqué précédemment dans mon exemple. Si on ajoutait None ça donnerait Union[int, str, None]
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  15. #15
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Oui, tu as raison.

  16. #16
    Membre averti

    Profil pro
    Enseignant
    Inscrit en
    Juillet 2003
    Messages
    296
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2003
    Messages : 296
    Points : 441
    Points
    441
    Par défaut
    Pour moi, le typage me sert à clarifier les objets, et utiliser IntelliSense efficacement. Après, je suis d’accord que ça ne sert à rien en fonctionnement. J’aime juste ne pas avoir de message d’erreur de PyLance et MyPy à cause d’une initialisation qui ne se fera pas immédiatement.

    Pour le moment, j’ai mis une série d’assert pour que Pylance soit content...

    Mais si un expert Python passe par ici et qu’une solution existe, je reste preneur.

    Pour info, je travaille sur Python 3.11 et VSCode (bizarrement, PyCharm ne ronchonne pas sur l’Optional sans assert, contrairement à VSCode)

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 048
    Points : 1 378
    Points
    1 378
    Par défaut
    Je vais me répéter mais est-ce que Ellipsis ne ferait pas l'affaire ? J'ai pas de quoi tester donc je pose la question .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.active_user: User = ...

  18. #18
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    J'avais essayé le typage avec Python mais il me semble que cela n'avait pas apporté grand chose...
    Je m'attendais à ce que cela fasse comme avec TypeScript

    Mais apparemment pour que cela fonctionne il fallait installer un module (et avoir un python >= à 3.10) si j'ai bien compris ?


    - Est-ce que le module permet d'améliorer l'autocomplétion ?
    Je suppose que pour cela il faudrait que les variables des scripts du projet soient typées ?

    - Si oui, alors pour les anciens scripts (librairie ou autre, pas forcément les notre) comment peut-on faire ?
    Est-ce qu'il y a un équivalent aux fichiers de déclaration de TypeScript ?


    Bon, la détection des erreurs de type c'est déjà un bon début...

  19. #19
    Membre averti

    Profil pro
    Enseignant
    Inscrit en
    Juillet 2003
    Messages
    296
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2003
    Messages : 296
    Points : 441
    Points
    441
    Par défaut
    Citation Envoyé par josmiley Voir le message
    Je vais me répéter mais est-ce que Ellipsis ne ferait pas l'affaire ? J'ai pas de quoi tester donc je pose la question .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.active_user: User = ...
    Pardon, je n’ai pas répondu à cette question. Non, hélas ça ne marche pas Ou alors je ne sais pas l’utiliser. J’avoue que je ne connaissais pas Ellipsis ailleurs que dans les listes…

Discussions similaires

  1. Réponses: 1
    Dernier message: 27/07/2009, 18h20
  2. Pb Variable saisie à l'ouverture du classeur pour utilisation ultérieure
    Par melouille56 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 10/01/2008, 23h57
  3. [DLL] Utilisation d'une DLL pour utiliser serveur Firebird
    Par sekiryou dans le forum Bases de données
    Réponses: 2
    Dernier message: 11/08/2004, 14h20
  4. [Debutant] probleme pour utiliser les classes d'un .jar
    Par pissek dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 12/05/2004, 18h21
  5. VCL de Crystal Report pour utilisation dans C++Builder
    Par dibak dans le forum C++Builder
    Réponses: 4
    Dernier message: 16/02/2004, 17h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo