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 :

Liste en compréhension avec condition IF ELSE


Sujet :

Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Janvier 2021
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : Janvier 2021
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Liste en compréhension avec condition IF ELSE
    Bonjour,

    j'ai une fonction qui doit me retourner la puissance d'un nombre et je dois utiliser les listes avec compréhension.
    Le test sur les paramètres n'était pas à faire mais j'aimerais comprendre.

    C'est le résultat de ma fonction sans prendre le test des paramètres
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def my_pow(m,b):
      if type(m) != int or type(b) != float:
        return None
      return  [b**m for m in range(0,m)]
     
    print("SI type(m) != int OU type(b) != float ALORS on retourne None")
    print(" - Pour type(m) != int   => ",my_pow(3.0,4))
    print(" - Pour type(b) != float => ",my_pow(3,4))
    print("SINON on calcule  b**m pour les valeurs du range")
    print(my_pow(3,4.0))
    et j'obtiens bien ce qu'il faut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SI type(m) != int OU type(b) != float ALORS on retourne None
     - Pour type(m) != int   =>  None
     - Pour type(b) != float =>  None
    SINON on calcule  b**m pour les valeurs du range
    [1.0, 4.0, 16.0]
    j'ai essayé en regardant la fonction ternaire d'inclure les tests mais j'ai plusieurs problèmes et j'aimerais comprendre pourquoi.
    J'ai écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def my_pow2(m,b):
      return  [b**m if isinstance(m, int) and isinstance(b, float) else None for m in range(0,m)]
    je ne comprends pas cette erreur quand je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    print("SI type(m) != int OU type(b) != float ALORS on retourne None")
    print(" - Pour type(m) != int   => ",my_pow2(3.0,4))
     
    Traceback (most recent call last):
      File "main.py", line 19, in <module>
        print(" - Pour type(m) != int   => ",my_pow2(3.0,4))
      File "main.py", line 16, in my_pow2
        return  [b**m if isinstance(m, int) and isinstance(b, float) else None for m in range(0,m)]
    TypeError: 'float' object cannot be interpreted as an integer
    alors que quand je fais l'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print("SI type(m) != int OU type(b) != float ALORS on retourne None")
    print(" - Pour type(b) != float => ",my_pow2(3,4))
    il retourne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SI type(m) != int OU type(b) != float ALORS on retourne None
     - Pour type(b) != float =>  [None, None, None]
    1. Pourquoi il ne gère pas isinstance du int - paramètre m - mais celui du float - paramètre b - oui ?
    2. Comment faire pour n'avoir qu'un retour et non une liste [None, None, None] ?


    Par avance merci pour toutes vos explications, liens qui pourraient me guider.

  2. #2
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 471
    Points : 6 109
    Points
    6 109
    Par défaut
    Bonjour,

    Ton erreur avec TypeError provient de ce que tu passes à range :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> range(0, 3.0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'float' object cannot be interpreted as an integer
    Pour ton autre problème, si tu veux utiliser la liste en compréhension et expr1 if condition else expr2, mais que ta fonction retourne un None à la place d'un [None, None, None], alors il faut sortir ce if-else de la liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def my_pow2(m,b):
      return [b**m for m in range(0,m)] if type(m) == int and type(b) == float else None
    Remarque pour la culture générale : en Python, pour faire des contrôles sur les types, la manière la plus lisible et la plus efficace est d'utiliser les annotations de type et de les vérifier avec un outil d'analyse statique du code comme mypy, mais ça demande un certain temps d'apprentissage.
    De Python 3.5 à Python 3.8, cela ressemblait à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from typing import List
     
    def my_pow3(m: int, b: float) -> List[float]:
      return [b**m for m in range(m)]
    À partir de Python 3.9, avec la PEP 585, la forme recommandée devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from __future__ import annotations
     
    def my_pow3(m: int, b: float) -> list[float]:
      return [b**m for m in range(m)]
    Mais tu n'es pas obligé d'étudier ça tout de suite.

  3. #3
    Candidat au Club
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Janvier 2021
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : Janvier 2021
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Bonsoir Pyramidev,

    Merci pour toutes ces explications, effectivement il y a encore beaucoup de choses à voir.
    Pour la liste en compréhension, je pensais, sûrement bêtement, que toutes les instructions devaient se situer entre les [].

    Encore merci

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Cath6689 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def my_pow(m,b):
      if type(m) != int or type(b) != float:
        return None
      return  [b**m for m in range(0,m)]
     
    print("SI type(m) != int OU type(b) != float ALORS on retourne None")
    print(" - Pour type(m) != int   => ",my_pow(3.0,4))
    print(" - Pour type(b) != float => ",my_pow(3,4))
    print("SINON on calcule  b**m pour les valeurs du range")
    print(my_pow(3,4.0))
    et j'obtiens bien ce qu'il faut :
    Pas tout à fait car tu forces "b" à être float. Ca t'interdit de calculer par exemple 4^3, calcul pourtant tout à fait licite.

    Et pour ta seconde fonction, tu ne peux pas utiliser "m" en tant que range() si "m" est d'un type incorrect. Tu dois donc d'abord tester "m" (et dans la foulée autant tester aussi "b") avant de générer ta liste en intension. Et bon même si c'est possible, il vaut mieux ne pas prendre un nom de variable déjà utilisé pour le corps de boucle (ie "m") car cela n'aide pas à la relecture.
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def my_pow(m,b):
    	if not isinstance(m, int) or not isinstance(b, (int, float)): return None
    	return  [b**x for x in range(m+1)]

    Citation Envoyé par Cath6689 Voir le message
    je pensais, sûrement bêtement, que toutes les instructions devaient se situer entre les [].
    Oui c'est possible, à condition que l'objet du contrôle ne soit pas utilisé malgré tout => return [b**x if isinstance(b, (int, float)) else None for x in range(m+1)]. Bref pour résumer, tout ce qui est utilisé après le "for" est présumé correct car de toute façon même s'il est incorrect, il sera quand-même utilisé.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Une liste en compréhension peut filtrer:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> def my_pow2(m,b):
    ...     return [b**m for m in range(m) if isinstance(m, int) and isinstance(b, (int, float)) ]
     
    ...
    >>> my_pow2(2,3)
    []
    >>> my_pow2(2,3.0)
    [1.0, 3.0]
    >>>
    cependant, ici, çà veut dire tester la condition à chaque itération qu'une seule fois avant suffirait.
    note: Il faut aussi "accepter" de retourner [] à la place de None... mais de toutes façon l'appelant devra tester le résultat.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Candidat au Club
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Janvier 2021
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Vosges (Lorraine)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs

    Informations forums :
    Inscription : Janvier 2021
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Un grand merci à vous tous
    Tout d'abord mille excuses de ne pas vous avoir répondu plus tôt, un peu obligée d'avancer dans la formation.
    Effectivement c'était une contrainte de l'exercice d'avoir b comme float ainsi que le retour None.

    Merci encore pour ces aides supplémentaires, il faudra que je refasse plus d'exercices

Discussions similaires

  1. [Python 2.X] liste de listes et tri avec condition sur les éléments d'une ou plusieurs listes
    Par nmokht97 dans le forum Calcul scientifique
    Réponses: 7
    Dernier message: 24/06/2016, 11h47
  2. [MYSQL 5.5] Liste des doublons avec conditions particulières
    Par flashguitou dans le forum Requêtes
    Réponses: 3
    Dernier message: 02/04/2014, 10h01
  3. Migration avec conditions if else
    Par raicolin dans le forum Exécution et industrialisation
    Réponses: 1
    Dernier message: 07/05/2013, 14h45
  4. [Batch] Problème syntaxe avec condition if ( ) else () pour NT
    Par carreau dans le forum Scripts/Batch
    Réponses: 3
    Dernier message: 14/10/2011, 18h45
  5. Réponses: 23
    Dernier message: 26/05/2008, 06h18

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