Tier une liste de dictionnaire selon un valeur

a marqué ce sujet comme résolu.

Bonjour,

Nouveau ici mais après avoir parcouru la forum, il me semble qu c’est pas mal du tout ! Entre les cours et le forum, je devrais avoir de la ressource pour mon petit niveau de code. Mais voilà, ça bloque déjà, j’en appelle à cotre aide.

Je cherche à faire une petit logiciel pour créer des tableaux de tournoi de ping.

J’ai donc 2 class (pour le moment), une Joueur et la Main

Dans Joueur.py, j’initialise les joueurs puis crée un dictionnaire avec 4 valeurs : prenom, nom, classement, club. Dans la Main.py, je crée mes joueurs et range les dictionnaires de joueurs dans un tableau. Je cherche à trier ce tableau par la valeur classement des dictionnaires. Et la… c’est le drame.

Joueurs.py

class Joueur:
    """ definir joueur"""


    def __init__(self,prenom, nom,classement,club):
        self.prenom = prenom
        self.nom = nom
        self.classement = classement
        self.club = club

    def show_joueur():
        tableau_joueur = {}
        #print(" prenom :",self.prenom," nom :",self.nom, "classement :" ,self.classement," club :",self.club)
        tableau_joueur["prenom"] = self.prenom
        tableau_joueur["nom"] = self.nom
        tableau_joueur["classement"] = self.classement
        tableau_joueur["club"] = self.club

Et Main.py

from Joueur import Joueur

index_joueur = []    

joueur1 = Joueur('damien', 'toto', 707, 'CAP')
joueur2 = Joueur('pierre', 'xeon', 652, 'bully')
joueur3 = Joueur('nico', 'pourpre', 1145, 'ecomoy')

index_joueur.append(joueur1)
index_joueur.append(joueur2)
index_joueur.append(joueur3)

index_joueur = sorted(tableau_joueur, key=lambda tri: tri['classement'])

for i in range(len(index_joueur)):
    print("index", i, 
          ", prenom:", index_joueur[i].prenom,
          ", nom:", index_joueur[i].nom,
          ", classement:", index_joueur[i].classement,
          ", club:", index_joueur[i].club,  )

ca me retourne:

NameError: name 'tableau_joueur' is not defined

Sans la method sorted, ma boucle me sort bien mon tableau avec mes valeur. C’est elle qui pose problème je pense. Il ne s’agit peut-être que d’une mauvaise formulation ou de manque de getter, bref, un peu paumé. Merci de votre aide.

Damien aka la padawan de service.

Salut,

Ce que l’erreur t’indique à sa manière, c’est que tableau_joueur n’est défini que dans la méthode show_joueur et pas en dehors.

Ensuite, ta clé de classement génèrera une erreur, parce que sur un objet Joueur, tu ne peux pas faire joueur["classement"]. Les joueurs ne sont pas des dictionnaires, ce sont des objets. Je pense que tu mélanges les deux concepts dans ta tête.

Je pense que ta ligne 13 devrait être plus comme ça :

index_joueur = sorted(index_joueur, key=lambda tri: tri.classement)

Cela devrait te débloquer.

Sinon, il y a beaucoup d’autres choses à dire sur ton code, est-ce que des conseils plus généraux t’intéressent ?

Et petite question, est-ce que tu as déjà programmé, même un peu, dans un autre langage que Python auparavant ?

+2 -0

Merci de ton retour en effet ca marche.

Il doit y avoir un peu de confusion mais surtout bcp de problème de syntaxe. J’en suis venu au forum car après avoir tester plusieurs choses, je saturai.

Sinon oui j’ai codé un peu car j’aime bien, mais ce n’est pas mon métier De l’AS3, un peu de python et de bash et une api un peu bizarre mais puissante en photo 360.

j’ai choisi ici le python car il me parait approprié et que c’est un bon langage à apprendre, même après 10 ans de pause.

Donc tout cela pour dire que oui je suis preneur de tes observations. Merci.

+0 -0

Alors, voici mes quelques remarques. J’essaie de les faire par ordre d’importance par rapport à là où tu sembles être dans ton apprentissage. Si certaines choses t’échappent, ce n’est pas très grave, chaque chose en son temps quand on apprend.

  1. Pour du code aussi court, je ne ferais qu’un fichier. Tu pourras toujours découper si nécessaire plus tard, et le faire prématurément complique pour rien.

  2. Le formattage du fichier aide à être clair. En Python, la plupart des gens suivent la convention qu’on appele "PEP-8". Perso, j’aime pas trop réfléchir à ce genre de choses, donc j’utilise un outil qui s’appelle black.

  3. Dans ta boucle, tu utilises un index pour parcourir ta liste. En Python, on préfère itèrer directement sur la liste (for joueur in joueurs: ...). Quand on veut l’index en plus, on utilise la fonction enumerate, qui renvoie des paires de valeurs qu’on peut scinder ensuite (voir le code ci-dessous).

  4. Personnellement, je préfère mettre le code principal dans une fonction, plutôt que de tout mettre en vrac. Là, j’ai créé une fonction "main", que j’appelle ensuite à la ligne 26. La ligne 25 est un idiome qu’on retrouve régulièrement. Ça permet d’exécuter la fonction seulement quand le script est exécuté (et pas quand il est importé). Le détail de fonctionnement est peut-être un peu prématuré pour toi, mais tu peux lire cette page si tu es curieux.

  5. C’est un peu du détail de style, mais tu peux créer tes joueurs directement dans une liste. Pas besoin de variables intermédiaires comme ça et c’est très lisible.

  6. Ta liste de joueurs (que j’ai renommée "joueurs", un nom au pluriel est souvent utilisé pour une collection d’éléments) peut se trier toute seule avec la méthode sort. Le résultat est similaire à sorted, mais c’est plus lisible (et sans copie de la liste).

  7. Pour l’affichage des chaînes de caractère, j’utilise une fonctionnalité très pratique de Python, les f-strings. Tu mets un f devant la chaîne de caractère, et ça te donne le droit de mettre des variables entre crochets qui permettra d’afficher leur contenu.

  8. À ce sujet, et c’est un peu du détail, j’ai choisi d’écrire une méthode __str__() pour Joueur. C’est ce qui permet à la ligne 22 à joueur de s’afficher avec tous les détails facilement. En interne, la fonction print va s’occuper d’utiliser cette méthode pour savoir quoi faire avec l’objet joueur.

Quand on met tout bout à bout et quelques autres bricoles, ça donne le code ci-dessous. :)

class Joueur:
    def __init__(self, prenom, nom, classement, club):
        self.prenom = prenom
        self.nom = nom
        self.classement = classement
        self.club = club

    def __str__(self):
        return f" prenom : {self.prenom}, nom : {self.nom}, classement : {self.classement}, club : {self.club}"


def main():
    joueurs = [
        Joueur("damien", "toto", 707, "CAP"),
        Joueur("pierre", "xeon", 652, "bully"),
        Joueur("nico", "pourpre", 1145, "ecomoy"),
    ]

    joueurs.sort(key=lambda j: j.classement)

    for index, joueur in enumerate(joueurs):
        print(f"{index}. {joueur}")


if __name__ == "__main__":
    main()
+2 -0

Je ne suis amusé à modifier ton code dans le sens que tu souhaitais (je pense).

J’ai placé quelques commentaires dans le code:

class Joueur:
    def __init__(self,prenom, nom,classement,club):
        self.prenom = prenom
        self.nom = nom
        self.classement = classement
        self.club = club
    def show_joueur(self):     # Si j'oublie le self, Ptython me dit qu'il manque un paramètre.
        tableau_joueur = {
            "prenom": self.prenom,
            "nom": self.nom,
            "classement": self.classement,
            "club": self.club
            }
        return tableau_joueur     # Si j'oublie le return, cela affiche None (pour rien du tout)

index_joueur = [Joueur('damien', 'toto', 707, 'CAP'), Joueur('pierre', 'xeon', 652, 'bully'), Joueur('nico', 'pourpre', 1145, 'ecomoy')]
for ij in index_joueur:
    print(ij.show_joueur())

Ce qui donne:

{'prenom': 'damien', 'nom': 'toto', 'classement': 707, 'club': 'CAP'}
{'prenom': 'pierre', 'nom': 'xeon', 'classement': 652, 'club': 'bully'}
{'prenom': 'nico', 'nom': 'pourpre', 'classement': 1145, 'club': 'ecomoy'}

Mais les suggestions de @Aabu sont préférables.

Merci de votre retour. Instructif en effet.

@PierrotLeFou, merci de ces commentaires. Je comprends mieux. J’ai toujours une trouvé inutile ce self à mettre partout… mais s’il en faut si peu pour le rendre heureux, je vais m’y plier.

@Aabu, merci de ces explications. J’en connais assez pour comprendre ce que tu as écris, reste à l’assimiler. Ton code est plus clair c’est indéniable.

J’aime bien séparé en Class car je trouve cela plus lisible sur le long terme. Même si ici, en effet, il est plus logique de tout mettre ensemble.

Ce code passe par des listes. Il me semblait plus logique de passer par des listes de dictionnaire. Ce code était un 1er jet. Dans la suite je souhaite manipuler les joueurs pour les mettre dans plusieurs liste créées avec des critères d’age et de classement entre autre. Un joueurs pouvant être dans plusieurs listes. Il me paraissait plus logique sur le long terme de manipuler des valeurs plutôt que des index dans une liste.

Donc la question qui vient est la suivante : est-ce que je passe par des listes de listes ou des listes de dictionnaires ?

En attendant je vais remettre tout cela au propre. Merci bcp à vous 2.

J’ai toujours une trouvé inutile ce self à mettre partout… mais s’il en faut si peu pour le rendre heureux, je vais m’y plier.

Quand une méthode est appelée sur un objet, l’objet est passé comme premier argument automatiquement par Python. Ce premier argument apparaît comme tous les autres, et on le nomme conventionnellement "self". Appeler une méthode sur un objet, c’est juste un appel de fonction normal avec une syntaxe spéciale.

Pour comprendre pourquoi le choix a été de faire ainsi, il faut plonger dans les entrailles de Python. Quoi qu’il en soit, ça peut paraître lourd au premier abord, mais il y a une bonne raison. :D

Inutile n’était pas le bon mot, mais un peu lourd oui

Python a quelques principes…

Explicit is better than implicit.

Voir le zen de python.

Python ne lie pas automatiquement les objets aux méthodes; le développeur doit spécifier ce lien avec self. Cela rend visible le fait que la méthode est liée à une instance et non à la classe elle-même.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte