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 :

Surcharge des parenthèses __call__ python


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2022
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2022
    Messages : 17
    Par défaut Surcharge des parenthèses __call__ python
    Salut à tous,

    Pour un projet de jeu de Reversi en Python en NSI, je dois implémenter une classe Plateau utilisant la surcharge des opérateurs () __call__ :

    class Plateau :
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
        def __init__ (self, long, haut):
            self.m_long = long
            self.m_haut = haut
            self.matrice = []
            for i in range (self.m_long*self.m_haut):
                self.matrice.append('_')
            """
            Initialisation de la classe Plateau, prenant un nombre de lignes et de colonnes comme paramètres,
            le plateau fonctionne à l'aide d'une matrice remplie au préalable d'underscores.
            """
     
        def __call__ (self, x, y):
            assert (x < self.m_long and y < self.m_haut, 'Coordonnées invalides')
            indice = y * self.m_haut + x
            return self.matrice[indice]
            """
            Surcharge des opérateurs () permettant d'accéder à une valeur de la matrice à l'aide de ses coordonnées.
            """
     
        def __repr__ (self):
            affichage = ""
            affichage += "   "
            for j in range (self.m_haut):
                affichage += str(j) + " "
            affichage += "\n"
            # Ligne du haut affichant les coordonnées x        
     
            for i in range(self.m_long):
                affichage += str(i) + "  "
                for j in range(self.m_haut):
                    affichage += str(self(i, j)) + " "
                affichage += "\n"
            # Affichage des coordonnées y et des valeurs de la matrice        
     
            return affichage
            """
            Affichage du Plateau sous la forme
               1 2 ...
            1  _ _
            2  _ _
            ...
            """
     
    plateau = Plateau(8, 8) # Plateau de jeu Reversi instancié avec 8 lignes et 8 colonnes
    print(plateau)
    print(plateau(0, 0)) # Affichage du coin en haut à gauche de la matrice
    plateau(0, 0) = 'X' # ligne faisant planter le programme
    L'affichage des cases fonctionne correctement avec la surcharge __call__, sauf que lorsqu'il s'agit de modifier une valeur, cette erreur s'affiche :
    SyntaxError: cannot assign to function call
    Or, le programme devrait juste changer la valeur de la case car la dernière ligne devrait accéder à plateau.matrice[0], sachant que le type du tableau est str, ce qui ne devrait pas poser problème.
    D'après le message d'erreur, il y aurait une erreur de syntaxe, je devrais utiliser les opérateurs ==, qui ne servent pas à affecter une nouvelle valeur, une case d'un tableau est pourtant sensée être modifiable, pourquoi non ici ?

    Merci d'avance.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 752
    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 752
    Par défaut
    Citation Envoyé par BluMonky Voir le message
    D'après le message d'erreur, il y aurait une erreur de syntaxe, je devrais utiliser les opérateurs ==, qui ne servent pas à affecter une nouvelle valeur, une case d'un tableau est pourtant sensée être modifiable, pourquoi non ici ?
    Ce n'est pas "il y aurait" mais c'est "il y a"... une erreur de syntaxe.
    En gros quoi que vous vouliez faire faire à l'interpréteur Python, il ne peut pas le décoder.
    Et ça n'a rien à voir avec ce que vous cherchez à faire mais avec la syntaxe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    >>> def f(): pass
    ...
    >>> f() = 123
      File "<stdin>", line 1
        f() = 123
        ^^^
    SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='?
    >>>
    De toutes façons, modifier la case d'un tableau sera toujours écrire tableau[indice] = valeur...

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

  3. #3
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 063
    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 063
    Par défaut
    L'erreur SyntaxError: cannot assign to function call se produit parce que Python interprète plateau(0, 0) = 'X' comme une tentative d'assignation à l'appel d'une fonction, ce qui n'est pas permis en Python.

    En Python, __setitem__ est l'opérateur utilisé pour définir le comportement d'assignation d'une valeur à un élément d'une liste ou un dictionnaire.

    Avec la possibilité d'assigner de cette manière,


  4. #4
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2022
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2022
    Messages : 17
    Par défaut
    Ça marche avec ce 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
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    class Plateau :
        def __init__ (self, long, haut):
            self.m_long = long
            self.m_haut = haut
            self.matrice = []
            for i in range (self.m_long*self.m_haut):
                self.matrice.append('_')
            """
            Initialisation de la classe Plateau, prenant un nombre de lignes et de colonnes comme paramètres,
            le plateau fonctionne à l'aide d'une matrice remplie au préalable d'underscores.
            """
     
        def __getitem__ (self, x, y):
            assert (x < self.m_long and y < self.m_haut, 'Coordonnées invalides')
            return self.matrice[y * self.m_haut + x]
            """
            Surcharge des opérateurs () permettant d'accéder à une valeur de la matrice à l'aide de ses coordonnées.
            """
     
        def __setitem__ (self, x, y, valeur):
            assert (x < self.m_long and y < self.m_haut, 'Coordonnées invalides')
            self.matrice[y * self.m_haut + x] = valeur
            return self
            """
            Surcharge des opérateurs [] permettant d'accéder à une valeur de la matrice à l'aide de ses coordonnées pour la modifier.
            """
     
        def __repr__ (self):
            affichage = ""
            affichage += "   "
            for j in range (self.m_haut):
                affichage += str(j) + " "
            affichage += "\n"
            # Ligne du haut affichant les coordonnées x        
     
            for i in range(self.m_long):
                affichage += str(i) + "  "
                for j in range(self.m_haut):
                    affichage += str(self.__getitem__(i, j)) + " "
                affichage += "\n"
            # Affichage des coordonnées y et des valeurs de la matrice        
     
            return affichage
            """
            Affichage du Plateau sous la forme
               1 2 ...
            1  _ _
            2  _ _
            ...
            """
     
    plateau = Plateau(8, 8) # Plateau de jeu Reversi instancié avec 8 lignes et 8 colonnes
    print(plateau)
    print(plateau.__getitem__(0, 0)) # Affichage du coin en haut à gauche de la matrice
    plateau.__setitem__(0, 0, 'X')
    print(plateau)
    Je vais fermer le topic.
    Merci de m'avoir aidé.

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 752
    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 752
    Par défaut
    On définit __getitem__ et __setitem__ pour ne pas les appeler directement:

    Citation Envoyé par BluMonky Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    plateau = Plateau(8, 8) # Plateau de jeu Reversi instancié avec 8 lignes et 8 colonnes
    print(plateau)
    print(plateau.__getitem__(0, 0)) # Affichage du coin en haut à gauche de la matrice
    plateau.__setitem__(0, 0, 'X')
    print(plateau)
    mais pouvoir écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    plateau = Plateau(8, 8) # Plateau de jeu Reversi instancié avec 8 lignes et 8 colonnes
    print(plateau)
    print(plateau[0,0]) # Affichage du coin en haut à gauche de la matrice
    plateau[0,0] = 'X'
    print(plateau)
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 063
    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 063
    Par défaut
    Tu n'utilises pas de très bonne manière ces méthodes spéciales, je t'avais montré un exemple d'utilisation. J'avais du temps, et avait créé mon code correction pour faire de la POO. Tu peux t'en servir pour adapter ton 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
    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
    44
    class Plateau:    
        def __init__(self, longueur, hauteur):
            self._longueur = longueur
            self._hauteur = hauteur
            self._matrice = ['_' for _ in range(longueur * hauteur)]
     
        @property
        def longueur(self):
            return self._longueur
     
        @property
        def hauteur(self):
            return self._hauteur
     
        def __getitem__(self, coordonnees):
            x, y = coordonnees
            self._verifier_coordonnees(x, y)
            return self._matrice[y * self._longueur + x]
     
        def __setitem__(self, coordonnees, valeur):
            x, y = coordonnees
            self._verifier_coordonnees(x, y)
            self._matrice[y * self._longueur + x] = valeur
     
        def _verifier_coordonnees(self, x, y):
            if not (0 <= x < self._longueur and 0 <= y < self._hauteur):
                raise ValueError('Coordonnées invalides')
     
        def __repr__(self):
            affichage = "  " + " ".join(str(j) for j in range(self._hauteur)) + "\n"
            for i in range(self._longueur):
                affichage += str(i) + " " + " ".join(self[i, j] for j in range(self._hauteur)) + "\n"
            return affichage
     
    # Exemple d'utilisation
    plateau = Plateau(8, 8)
    print(plateau)
    print()
    print("Valeur à la position (0, 0) : ", plateau[0, 0])
    print()
    plateau[0, 0] = 'X'
    print(plateau)
    print()
    print("Valeur à la position (0, 0) : ", plateau[0, 0])

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 836
    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 836
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par BluMonky Voir le message
    Pour un projet de jeu de Reversi
    J'aime bien ce jeu. Un jeu peu connu mais qui mériterait de l'être. J'ai été membre de la FFO à une époque, je me suis même classé dans les 30 premiers français et participé à des championnats internationaux. Accessoirement il y a une différence entre Othello (dans lequel on retourne dans toutes les directions) et Reversi (variante anglaise dans laquelle on ne retourne que dans une seule).

    Citation Envoyé par BluMonky Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Plateau :	
    	def __init__ (self, long, haut):
    		self.m_long = long
    		self.m_haut = haut
    		self.matrice = []
    		for i in range (self.m_long*self.m_haut):
    			self.matrice.append('_')
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Plateau :	
    	def __init__ (self, long=8, haut=8):
    		self.m_long = long
    		self.m_haut = haut
    		self.matrice = ["_",] * self.m_long * self.m_haut

    Citation Envoyé par BluMonky Voir le message
    """
    Surcharge des opérateurs () permettant d'accéder à une valeur de la matrice à l'aide de ses coordonnées.
    """
    Non. Surcharge de l'opérateur () permettant d'utiliser l'instance d'une classe comme si c'était une fonction. Bien comprendre les choses te permettra de bien les utiliser. Ceci dit, je ne vois pas trop en quoi c'est nécessaire ici.

    Ensuite il te faudra peut-être penser à différencier "calcul" et "affichage". Ce sera peut-être plus facile de gérer le jeu si celui-ci se compose en interne de 1, 0 et -1 (ou autres nombres) tandis que l'affichage se composera de "X" et de "O" (et pourra même être paramétrable)...
    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]

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

Discussions similaires

  1. [Python 3.X] Surcharge des opérateurs en Python
    Par User dans le forum Général Python
    Réponses: 11
    Dernier message: 12/04/2022, 11h41
  2. [MFC] Surcharger des fonctions de CView
    Par Philippe320 dans le forum MFC
    Réponses: 2
    Dernier message: 22/11/2005, 21h24
  3. Réponses: 2
    Dernier message: 15/11/2005, 10h59

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