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 :

Accéder aux attributs des objets dans une liste ? [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de Bidulbuk
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 54
    Par défaut Accéder aux attributs des objets dans une liste ?
    Bonjour à tout le monde !

    Je cherchais jusque-là vainement une occasion d'essayer Python et je viens d'en trouver une : j'aimerais réaliser un petit script de tour de parole (en gros que le script m'indique quelle personne a le moins parlé pour la faire passer en premier lors d'un tour de parole).

    J'ai donc créé une classe "Presents" destinée à répertorier les pseudos des personnes ainsi que leur temps de parole (je voudrais me laisser la possibilité de rajouter d'autres critères plus tard). Et j'ai mis dans une liste chaque Présent créé (donc avec son attribut de pseudo et son attribut de temps de parole).

    Mais je rencontre le problème suivant : dans ma liste, j'ai l'adresse de l'objet. Donc quand je veux comparer ou chercher des choses dans cette liste (par exemple vérifier que tel pseudo existe dans la liste), je dois rajouter à chaque item l'attribut dont j'ai besoin (soit le pseudo, soit le temps de parole) pour pouvoir faire cela. Et je ne sais pas si c'est possible, et, si c'est possible, comment m'y prendre.

    Est-ce que j'utilise une mauvaise manière de faire ? Pourriez-vous m'aider ?

    Voici mon code :
    Tour_de_parole.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    # Programme de tour de parole
    liste_de_presents = []
    tour_de_parole_ouvert = []
    
    
    # On définit une classe pour chaque individu
    class Presents:
        total = 0  # compte le nombre de présents
    def __init__(self, pseudo, tps_parole=0):
            Presents.total += 1  # on incrémente à chaque instance de classe créée
            self.pseudo = pseudo
            self.tps_parole = tps_parole
    
    
    def gerer_liste_de_presents():
        nombre_de_presents = input("Combien de personnes à ajouter aux présent.es ? : ")
        for i in range(int(nombre_de_presents)):
            pseudo_individu = input("Quel pseudo ? : ")
            pseudo_individu = Presents(pseudo_individu)
            liste_de_presents.append(pseudo_individu)
    
    
    def tour_de_parole():
        tour_de_parole_ouvert.clear()
        fermer_le_tour = "n"
        while fermer_le_tour != "o":
            nombre_inscrits = input("Combien de personnes veulent s'inscrire ? : ")
            for _ in range(int(nombre_inscrits)):
                inscrits_tour_parole = input("Qui veut parler ? : ")
                while inscrits_tour_parole not in liste_de_presents:
                    inscrits_tour_parole = input("Cette personne n'est pas inscrite. Qui veut parler ? : ")
                tour_de_parole_ouvert.append(inscrits_tour_parole)
                fermer_le_tour = input("Fermer le tour de parole ? (o/n) : ")
    
    
    gerer_liste_de_presents()
    tour_de_parole()
    Donc quand je compare les inscrits_tour_parole à liste_de_presents, je compare par exemple le pseudo "Pierre" à "[<__main__.Presents object at 0x7f0213717fd0>" alors que je devrais le comparer aux items de la liste de la façon suivante : item.pseudo. Et je n'arrive pas à faire ce que je voudrais.

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    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 : 4 062
    Par défaut
    Bonjour,

    Pouvez modifier votre code pour y mettre une indentation correcte ?

    Pour votre question, si j'ai bien compris,

    • Ajoutez une représentation sous forme de chaîne __str__ pour faciliter le debuggage et la visualisation des objets.
    • Pour vérifier si un pseudo est déjà présent dans la liste, vous pouvez utiliser une méthode qui parcourt la liste et vérifie l'attribut pseudo de chaque objet.
    • Modifiez la logique pour que l'ajout à tour_de_parole_ouvert se base sur l'objet et non sur une chaîne représentant le pseudo, pour garder la trace des informations de l'objet.


    EDIT: Vous pouvez mettre votre liste de Presents dans l'attribut de classe liste_de_presents.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Presents:
     
        liste_de_presents = []
     
        def __init__(self, pseudo, tps_parole=0):
            Presents.liste_de_presents.append(self)
            self.pseudo = pseudo
            self.tps_parole = tps_parole
     
        def __str__(self):
            return f"pseudo={self.pseudo}, tps_parole={self.tps_parole}"
     
     
    def gerer_liste_de_presents():
        nombre_de_presents = int(input("Combien de personnes à ajouter aux présent.es ? : "))
        for i in range(nombre_de_presents):
            pseudo_individu = input("Quel pseudo ? : ")
            if any(p.pseudo == pseudo_individu for p in Presents.liste_de_presents):
                print("Ce pseudo est déjà utilisé.")
                continue
            Presents(pseudo_individu)
     
    gerer_liste_de_presents()
     
    print(Presents.liste_de_presents)
    print([str(p) for p in Presents.liste_de_presents])
    EDIT 2:

    Autre solution (et il y en a d'autres, surtout conceptuelles), est d'utiliser la méthode de classe pour créer, ajouter si le pseudo n'existe pas, le présent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    class Presents:    
        liste_de_presents = []
     
        def __init__(self, pseudo, tps_parole=0):
            self.pseudo = pseudo
            self.tps_parole = tps_parole
     
        def __str__(self):
            return f"pseudo={self.pseudo}, tps_parole={self.tps_parole}"
     
        @classmethod
        def add_from_str(cls, pseudo_individu, tps_parole=0):
            if any(p.pseudo == pseudo_individu for p in cls.liste_de_presents):
                print(f"Le pseudo {pseudo_individu} est déjà utilisé.")
                return None
             cls.liste_de_presents.append(cls(pseudo=pseudo_individu, tps_parole=tps_parole))
     
    def gerer_liste_de_presents():
        nombre_de_presents = int(input("Combien de personnes à ajouter aux présent.es ? : "))
        for i in range(nombre_de_presents):
            pseudo_individu = input("Quel pseudo ? : ")
            Presents.add_from_str(pseudo_individu=pseudo_individu, tps_parole=0)
     
    gerer_liste_de_presents()
     
    print(Presents.liste_de_presents)
     
    print([str(p) for p in Presents.liste_de_presents])

  3. #3
    Membre averti Avatar de Bidulbuk
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 54
    Par défaut
    Merci beaucoup de ta réactivité !

    Je ne connaissais pas le __str__ ni le any, qui est exactement ce que je cherchais ! Et je ne savais pas qu'on pouvait utiliser quelque chose comme "Presents.liste_de_presents.append(self)", c'est plus simple effectivement.

    Dans mon script, la liste de présents n'est pas la même chose que le tour de parole ouvert (les présents sont les personnes qui peuvent s'inscrire sur le tour de parole, mais tous les présents ne veulent pas forcément prendre la parole). Je vais ré-écrire la deuxième partie du code en me basant sur tes explications (mais je vois à peu près comment faire si je dois faire comme tu dis et garder les attributs de l'objet, il faudrait que je copie un item de la liste de présents dans la liste tour de parole) mais pour moi ma question est résolue

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    bonjour

    Citation Envoyé par Bidulbuk Voir le message
    "Presents.liste_de_presents.append(self)", c'est plus simple effectivement.
    Quelle drole idée de mettre la liste dans la classe "Present"... Cela n'apporte rien ! Et normalement une classe ne doit faire qu'une chose.

    Citation Envoyé par Bidulbuk Voir le message
    il faudrait que je copie un item de la liste de présents dans la liste tour de parole
    Tu cherches a compliquer ?
    Simplement ajouter un attribut à chaque personne "inscite" ou non. Cela permet de n'avoir qu'une seule liste et ensuite on applique un filtre (sur cet attribut)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def init_liste_inscrits(presents): 
        print()
        for present in presents:
            yes = input(f"{present.name} va prendre la parole ? ")
            if not yes:
                present.inscrit = False
    Pour la fonction gerer_liste_de_presents()
    Au lieu de demander un nombre, il est plus pratique de tester si le résultat est vide , alors sortir (même chose pour le tour de parole)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        while True:
            pseudo = input("Ajout d'une personne, son pseudo ? : ")
            if not pseudo:
                break
            if not in_list(presents, pseudo):  # a définir ce test
                presents.append(Present(pseudo))
    Pour ta fonction tour_de_parole() on a presque le même code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
        while True:
            pseudo = input("Qui parle ? ").strip()
            if not pseudo:
                break
            present = in_list(presents, pseudo)  # a définir ce test
            if not present or not present.inscrit:
                print(pseudo, "Non trouvé dans les inscrits !")
                continue
     
            long = int(input(f"Durée de parole de {present.name} ? "))
            present.long += long
     
            # trier et afficher le résultat intermédiaire  (Present a la methode __lt__() )
            for present in sorted(presents):
                if present.inscrit:
                    print(present)


    EDIT

    Citation Envoyé par Bidulbuk Voir le message
    indique quelle personne a le moins parlé pour la faire passer en premier lors d'un tour de parole).
    Je comprends donc qu'il y a plusieurs tours si elle doit parler au prochain ?
    Il serait alors normal que "self.tps_parole" soit alors un dictionnaire de "tps_parole" (ou une classe) ?

  5. #5
    Membre averti Avatar de Bidulbuk
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Lozère (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 54
    Par défaut
    Merci des retours !

    Alors comme je suis un débutant total, je ne comprends pas encore toutes les indications fournies.

    Oui, les tours de paroles sont potentiellement infinis. Chaque tour de parole est ouvert pour que les personnes s'inscrivent si elles veulent parler. Une fois que tout le monde a parlé, on ré-ouvre un tour de parole, et ainsi de suite.

    Je m'en suis sorti comme ça pour le moment (j'ai remis la liste des présents en dehors de la classe Présents parce que c'est plus clair pour moi d'avoir la liste des listes au début de mon code) :

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def tour_de_parole_ouvert():
        tour_de_parole.clear()
    
        fermer_tour = "n"
    while fermer_tour == "n":
            nombre_volontaires = input("Combien de personnes veulent s'inscrire sur le tour de parole ? : ")
    
            for _ in range(int(nombre_volontaires)):
                inscrit = False
                while not inscrit:
                    volontaire = input("Nom de la personne à inscrire : ")
                    if any(volontaire == p.pseudo for p in liste_de_presents):
                        inscrit = True
                        for i in liste_de_presents:
                            if volontaire == i.pseudo:
                                tour_de_parole.append(i)
            fermer_tour = input("Voulez-vous fermer le tour de parole ? (o/n) : ")

    Ca me permettra de trier en fonction des attributs de classe.

    ________________________________

    Code complet pour le moment :
    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    # Programme de tour de parole
    
    liste_de_presents = []
    tour_de_parole = []
    
    
    # On définit une classe pour chaque individu
    
    class Presents:
    
        def __init__(self, pseudo, tps_parole=0):
            self.pseudo = pseudo
    self.tps_parole = tps_parole
    
    def __str__(self):
            return self.pseudo + " a parlé " + str(self.tps_parole) + " minutes."
    
    
    def gerer_liste_de_presents():
        nombre_de_presents = int(input("Combien de personnes à ajouter aux présent.es ? : "))
        for i in range(nombre_de_presents):
            pseudo_individu = input("Quel pseudo ? : ")
            liste_de_presents.append(Presents(pseudo_individu))
    
    
    def tour_de_parole_ouvert():
        tour_de_parole.clear()
    
        fermer_tour = "n"
    while fermer_tour == "n":
            nombre_volontaires = input("Combien de personnes veulent s'inscrire sur le tour de parole ? : ")
    
            for _ in range(int(nombre_volontaires)):
                inscrit = False
                while not inscrit:
                    volontaire = input("Nom de la personne à inscrire : ")
                    if any(volontaire == p.pseudo for p in liste_de_presents):
                        inscrit = True
                        for i in liste_de_presents:
                            if volontaire == i.pseudo:
                                tour_de_parole.append(i)
            fermer_tour = input("Voulez-vous fermer le tour de parole ? (o/n) : ")

  6. #6
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    Ce n'est pas bien de travailler le dimanche
    Citation Envoyé par Bidulbuk Voir le message
    Alors comme je suis un débutant total, je ne comprends pas encore toutes les indications fournies.

    Oui, les tours de paroles sont potentiellement infinis.
    C'est bien pourquoi j'ai évoqué une structure ou l'on remplace ton attribut "temps de parole" par une liste !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Tour:
        def __init__(self, inscrit = False):
            self.inscrit = inscrit
            self.length = 0
        def __str__(self):
            return f"{self.length:3}" if self.inscrit else '  -'
     
    class Person:
        def __init__(self, nom):
            self.name = nom.strip()
            self.tours : list[Tour] = []  # enreg du scrore et si on participe ou non, a chaque tour on fait un ajout
        def average(self):
            pass    #TODO
        def __str__(self):
            tours = " ".join(str(t) for t in self.tours)
            return f"{self.average():4} {tours} {self.name}"
    On enregistre chaque tour, et à chaque on affiche un tableau récap du type:
    PS: en fait c'est cette sortie qui est le cahier des charges et qui va donc entrainer une structure particulière pour ce besoin.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     MOY  tours (3)     pseudo
       3   3   -   -    tot    # 1 seul tour
       8   -  12   4    tit    # tours 2 et 3
      15   8   7  32    tat    # tours 1,2 et 3 a participé
    La première colonne donne la moyenne par tour inscrit

    En gros , le programme complet, avec cette structure, peut-être:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    presents = init_liste_presents()
     
    for tour in range(12):
        print(f"\nTour {tour+1}...")
        continuer = init_liste_inscrits(presents, tour)    # simple ajout dans self.tours avec inscrit ou non, a chaques personnes
        if not continuer:  # aucun inscrit
            break
        tour_de_parole(presents, tour) 
        # un mini rapport des inscrits(uniquement)
        for present in sorted(presents):
            if present.tours[tour].inscrit:
                print(present)
     
    # rapport de fin
    print()
    print("-"*24)
    print(f"TOTAL  MOYENNE  tours {len(presents[0].tours)}    pseudo")
    for present in sorted(presents):
        # soyons fou, on ajoute le total de prise de parole
        print(f"{present.total():4}", present)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/08/2017, 11h39
  2. Liste des objets dans une Forms
    Par yasstunisien dans le forum Forms
    Réponses: 1
    Dernier message: 15/09/2011, 14h51
  3. Comment Manipuler des objets dans une liste de type TList ?
    Par PadawanDuDelphi dans le forum Delphi
    Réponses: 1
    Dernier message: 02/11/2006, 15h40
  4. [Lisp] Suppression des parenthèses dans une liste
    Par bourdaillet dans le forum Lisp
    Réponses: 3
    Dernier message: 19/12/2004, 21h02
  5. [langage] Comment rajouter des champs dans une liste
    Par toto_titi dans le forum Langage
    Réponses: 4
    Dernier message: 28/08/2003, 14h09

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