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 :

Portée des variables de classe


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de Pierrot92320
    Homme Profil pro
    Ingénieur en retraite (électronique)
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur en retraite (électronique)
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut Portée des variables de classe
    Bonjour

    Je suis actuellement plongé dans l'excellent livre "Apprendre à programmer avec Python 3" de G.S. A la page "espaces de noms des classes et instances" il est écrit que :
    --- Chaque classe possède son espace de noms (contenant les variables de classe), et chaque objet instance possède son espace de noms (contenant les variables d'instance).
    --- Les instances peuvent utiliser, mais pas modifier, les variables de classe.

    J'ai du mal à comprendre ce dernier point car en exécutant ce script :

    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
     
    class Bidon(object):
        """essais de portée des variables"""
        var1 = 11       
     
    print(Bidon.var1)       # Variable de classe ?
     
    obj1 = Bidon()
    obj1.var1 = 0           # Variable d'instance ?
    print(obj1.var1)        # La variable d'instance est modifiée
     
    print(Bidon.var1)       # et la variable de classe aussi
     
    obj2 = Bidon()          # D'ailleurs les nouveaux objets ne sont plus
    print(obj1.var1)        # instanciés avec la même valeur de var1
    ... on constate que la variable Bidon.var1 a été modifiée par l'instance obj2.

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Je ne comprends pas; quand j'exécute ton code, à la ligne 12, la variable de classe vaut toujours 11, elle n'a pas été modifiée. Et la dernière ligne, je suppose que tu voulais écrire obj2.var1 (qui renvoie toujours 11 aussi) ?

    Par contre, je ne suis pas vraiment d'accord avec:
    --- Les instances peuvent utiliser, mais pas modifier, les variables de classe.
    Les instances peuvent modifier la variable de classe (Bidon.var1), mais il faut passer par la classe, pas par self. On ne peut pas la modifier en passant par self car cela crée une variable d'instance qui masque la variable de classe.

  3. #3
    Membre confirmé Avatar de Pierrot92320
    Homme Profil pro
    Ingénieur en retraite (électronique)
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur en retraite (électronique)
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    Citation Envoyé par dividee Voir le message
    On ne peut pas la modifier en passant par self car cela crée une variable d'instance qui masque la variable de classe.
    Excusez-moi. Vous avez raison, mon exemple est mauvais car je m'aperçois que j'ai mal interprété le problème.

    Le code suivant est plus fidèle au problème que je rencontre :
    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
    class Bidon(object):
        var1 = [11]
     
    obj1 = Bidon()
    obj2 = Bidon()
    print("obj1.var1 =", obj1.var1)     # Pour les deux instances 
    print("obj2.var1 =", obj2.var1)     # on a bien var1 = [11]
     
    obj1.var1[0] = 33                   # On modifie la variable
    print("obj1.var1 =", obj1.var1)     # d'instance de obj1 et celle de
    print("obj2.var1 =", obj2.var1)     # obj2 est également modifiée
     
    print("Bidon.var1 =", Bidon.var1)   # La variable de classe est 
    obj3 = Bidon()                      # également modifiée, ainsi
    print("obj3.var1 =", obj3.var1)     # que les nouvelles instances
    Il semble que ce comportement soit lié au type "liste" de var1. Car si je choisis le type entier cela fonctionne comme prévu :
    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
    class Bidon(object):
        var1 = 11
     
    obj1 = Bidon()
    obj2 = Bidon()
    print("obj1.var1 =", obj1.var1)     # Pour les deux instances 
    print("obj2.var1 =", obj2.var1)     # on a bien var1 = 11
     
    obj1.var1 = 33                      # On modifie la variable
    print("obj1.var1 =", obj1.var1)     # d'instance de obj1 et celle
    print("obj2.var1 =", obj2.var1)     # de obj2 n'est pas modifiée
     
    print("Bidon.var1 =", Bidon.var1)   # La variable de classe 
    obj3 = Bidon()                      # n'est pas modifiée ni
    print("obj3.var1 =", obj3.var1)     # les nouvelles instances

  4. #4
    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
    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 Bidon(object):
        def __init__(self):
            self.var1 = [11]
     
    obj1 = Bidon()
    obj2 = Bidon()
    print("obj1.var1 =", obj1.var1)     # Pour les deux instances 
    print("obj2.var1 =", obj2.var1)     # on a bien var1 = [11]
     
    obj1.var1[0] = 33                   # On modifie la variable
    print("obj1.var1 =", obj1.var1)     # d'instance de obj1 et celle de
    print("obj2.var1 =", obj2.var1)     # obj2 est également modifiée
     
    print("Bidon.var1 =", Bidon.var1)   # La variable de classe est 
    obj3 = Bidon()                      # également modifiée, ainsi
    print("obj3.var1 =", obj3.var1)     # que les nouvelles instances
    Ça fera ce que vous voulez.

    En ne mettant pas self devant votre variable var, vous dites que var n'appartient pas à l'instance mais à la classe.

    Si vous modifiez une variable de classe, chaque instance créée sera effectuée en considérant la nouvelle valeur de var1.

    Maintenant si vous voulez modifier la variable d'une instance, vous devez exprimer l'appartenance de la variable var1 à l'objet à l'aide de self (convention comme this pour le C++ ou java)

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 180
    Par défaut
    Bonjour

    Ceci est tout à fait normal, même si cela parait bizarre. En fait dans la classe
    ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    class Maclasse(object):
        var1 = 2
        var2 = 'abc'
        var3 = (7,8)
        tableau = []
        dico = dict()
    var1, var2, var3 sont des variables de classes non mutables .
    C'est à dire que tout changement de valeur crée une nouvelle référence.
    A titre d'essais, utilise la fonction prédéfinie id(self.var1) par exemple. Tu constateras que, après modification, l'id a changé. C'est à dire que pour faire la modif demandée, python a effectué une copie de la variable avec une nouvelle valeur. L'ancienne valeur n'étant plus référencée, elle sera détruite par le garbage collector.

    En revanche, tableau et dico sont des variables mutables.
    Il n'y a pas une nouvelle instanciation à chaque modif.

    Quoi qu'il en soit, le bon "truc" pour modifier une variable de classe depuis une instance, c'est de faire quelque chose du style.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a = Maclasse()
    a.__class__.var1 = 10
    a.__class__.tableau.append(18)
    Le code n'en sera que plus lisible.

  6. #6
    Membre expérimenté
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 180
    Par défaut
    PS : Désolé, Fred, le temps que je réponde, tu avais apporté la tienne

  7. #7
    Membre confirmé Avatar de Pierrot92320
    Homme Profil pro
    Ingénieur en retraite (électronique)
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur en retraite (électronique)
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    Incroyable !

    Si, à la ligne 9 du script, je remplace
    par
    ou même par
    tout devient normal.

    Expliquez moi SVP

  8. #8
    Membre confirmé Avatar de Pierrot92320
    Homme Profil pro
    Ingénieur en retraite (électronique)
    Inscrit en
    Avril 2009
    Messages
    159
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur en retraite (électronique)
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 159
    Par défaut
    Merci Fred et chticricri.

    J'ai modifié mon texte alors que vous aviez commencé à préparer vos réponses excusez-moi je ne le ferai plus ! Je pense avoir compris vos explications, je vais méditer dessus.

  9. #9
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Quand tu écris obj1.var1[0] = 33, ça veut dire "remplacer le premier élément de la liste référencée dans l'attribut var1 de obj1 par 33". Tu ne modifies pas var1, mais l'objet (la liste, dans ce cas-ci) référencé par var1. var1 contient toujours la même liste, mais le contenu de cette liste a changé. En fait, si var1 était une variable de classe, cette ligne ne créerait pas de variable d'instance var1 dans obj1, mais irait chercher la variable de classe directement, car l'accès à var1 ne se fait qu'en lecture.

    obj1.var1 = [33], quant à lui, crée une nouvelle liste qui contient 33 et l'assigne à var1. Et comme c'est une écriture, il créerait dans ce cas une variable d'instance dans obj1 qui masquerait la variable de classe.

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

Discussions similaires

  1. [Débutant] Portée des variables dans une classe
    Par Jah73 dans le forum VB.NET
    Réponses: 24
    Dernier message: 10/10/2013, 14h55
  2. Portée des variables entre classes
    Par Gnifrus dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 03/03/2013, 14h37
  3. [POO] Portée des variables de classe
    Par guidav dans le forum Langage
    Réponses: 3
    Dernier message: 31/01/2007, 19h27
  4. [XSL]Problème de portée des variables
    Par djulesp dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 17/09/2004, 10h34
  5. [Portée] portée des variables
    Par parksto dans le forum Langage
    Réponses: 7
    Dernier message: 09/05/2004, 21h05

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