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 :

Compréhension création de classe


Sujet :

Python

  1. #1
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2011
    Messages : 28
    Points : 14
    Points
    14
    Par défaut Compréhension création de classe
    Comment comprendre la différence entre ceci
    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
    #-*- coding: iso-8859-15 -*-
     
    class personne:
        def __init__(self,nom):
            self.nom=nom
            self.dico={}
            self.dico['cree']=nom
        def fiche(self):
            print ('mon nom est: %s et d=%s') % (self.nom,self.dico)
    e={}
     
    e[0]=personne('alice')
    e[0].dico['zero']='zero'
    e[0].fiche()
    e[1]=personne('bernard')
    e[1].dico['un']='un'
    e[1].fiche()
    e[0].fiche()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mon nom est: alice et d={'zero': 'zero', 'cree': 'alice'}
    mon nom est: bernard et d={'un': 'un', 'cree': 'bernard'}
    mon nom est: alice et d={'zero': 'zero', 'cree': 'alice'}
    qui donne bien un dico par personne et cela

    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
    #-*- coding: iso-8859-15 -*-
     
    class personne:
        nom=''
        dico={}
        def __init__(self,nom):
            self.nom=nom
            self.dico['cree']=nom
        def fiche(self):
            print ('mon nom est: %s et d=%s') % (self.nom,self.dico)
    e={}
     
    e[0]=personne('alice')
    e[0].dico['zero']='zero'
    e[0].fiche()
    e[1]=personne('bernard')
    e[1].dico['un']='un'
    e[1].fiche()
    e[0].fiche()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mon nom est: alice et d={'zero': 'zero', 'cree': 'alice'}
    mon nom est: bernard et d={'zero': 'zero', 'un': 'un', 'cree': 'bernard'}
    mon nom est: alice et d={'zero': 'zero', 'un': 'un', 'cree': 'bernard'}
    qui crée un dico commun pour les personnes et un nom différent?

    Merci d'apporter de la lumière à ma compréhension du fonctionnement de Python

  2. #2
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Houlà : ton exemple est bien compliqué !

    Plus simplement :

    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 Classe(object):
    ...     c = 0
    ...
    >>> Classe.c
    0
    >>> 
    >>> Classe.__dict__
    dict_proxy({'__dict__': <attribute '__dict__' of 'Classe' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Classe' objects>, 'c': 0, '__doc__': None})
    >>>
    >>> obj1 = Classe()
    >>> obj2 = Classe()
    >>> 
    >>> obj1.__dict__
    {}
    >>> 
    >>> obj1.c = "je la joue perso"
    >>> 
    >>> obj1.__dict__
    {'c': 'je la joue perso'}
    >>> 
    >>> obj1.c
    'je la joue perso'
    >>> Classe.c
    0
    >>> obj2.c
    0
    >>> obj2.__dict__
    {}
    c est, à la base, un attribut de classe, commun à toutes les instances. On ne le retrouve pas dans les attributs propres à une instance (lignes 13 et 14), seulement dans les attributs de la classe (lignes 7 et 8).

    Si une instance décide de se particulariser et de la "jouer perso", un attribut qui lui est propre est créé (lignes 16 à 19). Les autres instances n'auront toujours pas d'attribut "c" propre (lignes 25 à 28).

    Je n'ai pas (re)trouvé dans la doc officielle ce "truc". Mais, pour faire court, "c'est comme ça", faut faire avec.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  3. #3
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2011
    Messages : 28
    Points : 14
    Points
    14
    Par défaut
    Merci pour la réponse.
    C'est limpide, je comprends...

    Bonnes fêtes!

  4. #4
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Avec plaisir. Bonnes fêtes à toi aussi !
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  5. #5
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Citation Envoyé par plxpy Voir le message
    Je n'ai pas (re)trouvé dans la doc officielle ce "truc". Mais, pour faire court, "c'est comme ça", faut faire avec.
    C'est vrais qu'une explication manque sur le fonctionnement interne de la machine.

    Le comportement étant trop proche des paramètres par défaut pour les fonctions il m'est difficile de ne pas faire le parallèle.
    Pour rappel sur les paramètres par défaut, la doc officielle étant succincte (The default values are evaluated at the point of function definition in the defining scope).
    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
    >>> def f(l=[]):
    ...     l.append(0)
    ...     return l
    ... 
    >>> f()
    [0]
    >>> f()
    [0, 0]
    >>> f()
    [0, 0, 0]
    >>> id(f())
    3074972876L
    >>> id(f())
    3074972876L
    >>> id(f())
    3074972876L
    >>> f()
    [0, 0, 0, 0, 0, 0, 0]
    Nous avons bien ici le même objet (la fonction f, id 3074972876L), l'utilisation de la méthode se fait donc sur la même liste.

    Pour les instances cela vas de même
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> class Foo:
    ...     value = 0
    ... 
    >>> f = Foo()
    >>> f.__class__
    <class __main__.Foo at 0xb7745c8c>
    >>> f1 = Foo()
    >>> f1.__class__
    <class __main__.Foo at 0xb7745c8c>
    On utilise donc bien le même objet bien que les instances soit différentes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> f
    <__main__.Foo instance at 0xb7485e8c>
    >>> f1
    <__main__.Foo instance at 0xb7485c6c>
    Pour ce qui est de 'la jouer perso' la résolution de l'attribut commence par l'espace de nom de l'instance.
    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
    >>> class Foo(object):
    ...     classattr = "class"
    ... 
    >>> f = Foo()
    >>> f.classattr
    'class'
    >>> id(f.classattr)
    3077724160L
    >>> f.__class__.classattr
    'class'
    >>> id(f.__class__.classattr)
    3077724160L
    >>> f.classattr = "instance"
    >>> f.__dict__
    {'classattr': 'instance'}
    >>> f.classattr
    'instance'
    >>> id(f.classattr)
    3077621664L
    >>> f.__class__.classattr
    'class'
    >>> id(f.__class__.classattr)
    3077724160L
    L'attribut créé est donc bien propre à l'instance.

    @+ et bonnes fêtes
    Merci d'utiliser le forum pour les questions techniques.

  6. #6
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 774
    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 : 3 774
    Points : 7 020
    Points
    7 020
    Par défaut
    On utilise donc bien le même objet bien que les instances soit différentes.
    Je dirais plutôt que les instances sont les objets, et qu'ils diffèrent (heureusement). Les classes sont les patrons de ces objets et il est normal que eux ne diffèrent pas...
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  7. #7
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Les classes aussi sont des objets, au sens interprétation du code.
    When a class definition is entered, a new namespace is created, and used as the local scope — thus, all assignments to local variables go into this new namespace. In particular, function definitions bind the name of the new function here.

    When a class definition is left normally (via the end), a class object is created. This is basically a wrapper around the contents of the namespace created by the class definition; we’ll learn more about class objects in the next section. The original local scope (the one in effect just before the class definition was entered) is reinstated, and the class object is bound here to the class name given in the class definition header (ClassName in the example).
    Dans ce sens tout ce qui est dit plus haut explique que cela n'est qu'un parcours des espaces de noms, l'objet classe ayant le siens qui est créé lors de la lecture du code.
    Merci d'utiliser le forum pour les questions techniques.

  8. #8
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 774
    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 : 3 774
    Points : 7 020
    Points
    7 020
    Par défaut
    Ok, on s'est mal compris, je parlais dans un sens concret du problème et non de la syntaxe.

    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  9. #9
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Citation Envoyé par fred1599 Voir le message
    Les classes sont les patrons de ces objets et il est normal que eux ne diffèrent pas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    >>> class Foo:
    ...     classattr = 0
    ...     def changeattr(self, newattr):
    ...          self.__class__.classattr = newattr
    ... 
    >>> f = Foo()
    >>> f.classattr
    0
    >>> f.changeattr(1)
    >>> f.classattr
    1
    >>> f1 = Foo()
    >>> f1.classattr
    1
    Cela reste un namespace et Python reste très dynamique... (et je ne parle pas des mutables)

    @+
    Merci d'utiliser le forum pour les questions techniques.

  10. #10
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 774
    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 : 3 774
    Points : 7 020
    Points
    7 020
    Par défaut
    Les classes sont les patrons de ces objets et il est normal que eux ne diffèrent pas
    Ce que je veux dire, c'est que l'on peut modifier un dessin technique (une classe) parce-qu'on a fait un oubli ou fait une erreur, il en reste pas moins que la classe une fois créée permet la construction de différents objets (instances) et cette classe ne changera pas, on partira toujours du même dessin technique pour la construction.

    Si on veut changer le comportement de cette classe, on utilisera l'héritage...

    Si on veut créer/modifier dynamiquement une classe, on parlera de metaclass, mais...

    Citation Envoyé par Tim Peters
    Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
    ça reste des cas très spécifiques.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  11. #11
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    ça reste des cas très spécifiques.
    Oui...
    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
    class Storage(object):
        _singleton = None
        datas = []
        def __new__(cls, *args, **kwargs):
            if not cls._singleton:
                cls._singleton = super(Storage, cls).__new__(cls, *args, **kwargs)
            return cls._singleton
        def add(self, newdata):
            self.datas.append(newdata)
        def getdata(self):
            return self.datas
        # ...
     
     
    s = Storage()
    s.add(1)
    s1 = Storage()
    print(s1.getdata())
    print(id(s) == id(s1))
    print(s is s1)
    Mais là c'est plus que du hors sujet (et turbocapillotracté comme dirait quelqu’un)

    @+
    Merci d'utiliser le forum pour les questions techniques.

  12. #12
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 774
    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 : 3 774
    Points : 7 020
    Points
    7 020
    Par défaut
    Oui, oui mais quand tu modifieras s1, tu modifieras s, ce qui signifie qu'il n'y a en fait qu'une seule instance, mais j'ai toujours eu du mal à voir l'intérêt du singleton que je trouve contre intuitif au principe de base de la classe qui est :
    Une classe permet la construction de plusieurs objets (instances)

    Je n'en perd pas moins qu'il peut être utile, cependant l'inconvénient est de laisser la possibilité de créer une autre instance, trompeur pour l'utilisateur de cette classe, il pourrait croire utiliser un autre objet (différent) alors que ce n'est pas le cas. Il est préférable de lui interdire l'instanciation (le principe du singleton).
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  13. #13
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    L'exemple du singleton (toujours aussi controversé comme pattern ) n'est là que pour l'utilisation de _singleton.
    Citation Envoyé par fred1599 Voir le message
    Il est préférable de lui interdire l'instanciation (le principe du singleton).
    C'est ce qui est fait dans la PEP318
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def singleton(cls):
        instances = {}
        def getinstance():
            if cls not in instances:
                instances[cls] = cls()
            return instances[cls]
        return getinstance
     
    @singleton
    class MyClass:
        ...
    Merci d'utiliser le forum pour les questions techniques.

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 203
    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 203
    Points : 36 631
    Points
    36 631
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Oui, oui mais quand tu modifieras s1, tu modifieras s, ce qui signifie qu'il n'y a en fait qu'une seule instance, mais j'ai toujours eu du mal à voir l'intérêt du singleton que je trouve contre intuitif au principe de base de la classe qui est :
    Une classe permet la construction de plusieurs objets (instances).
    Une classe permet de fabriquer une collection d'objets semblables.
    Une collection peut être vide, réduite à N éléments, permettre la création d'un nombre indéfini d'éléments différents (au sens "is").

    singleton, monostate, Borg permettent de traduire ces différentes propriétés.
    Ce sont des patterns de "design".
    Coder ces propriétés sera plus ou moins ardu suivant le langage.
    Il ne sera pas toujours utile ni nécessaire qu'il y ait bijection entre collection au sens "design" et sa réalisation en code.

    c'est que l'on peut modifier un dessin technique (une classe) parce-qu'on a fait un oubli ou fait une erreur, il en reste pas moins que la classe une fois créée permet la construction de différents objets (instances) et cette classe ne changera pas, on partira toujours du même dessin technique pour la construction.
    Supposons que l'objet soit une "chaise".
    Un caillou, un tabouret,... quoi que ce soit pourvu qu'on puisse poser ses fesses dessus fera l'affaire. Il y a pleins de façons pour fabriquer un objet utilisable en tant que chaise.
    En Python, on appelle cela "duck typing".

    Hmm, bonnes fêtes!
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. [RMI] problème Création *_stub.class et *_skel.class
    Par philobedo dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 29/05/2006, 21h03
  2. Contrôler l'ordre de création de classes globales
    Par 10_GOTO_10 dans le forum C++
    Réponses: 4
    Dernier message: 24/04/2006, 21h39
  3. Création de classe exception
    Par HNT dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 03/01/2006, 16h53
  4. Création de classes à la volée...
    Par ouiffi dans le forum Langage
    Réponses: 8
    Dernier message: 16/12/2005, 19h01

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