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 :

Classe dérivée de 'list' récalcitrante !


Sujet :

Python

  1. #1
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut Classe dérivée de 'list' récalcitrante !
    Bonjour à tous (et à toutes),

    je me suis fais une petite classe dérivée de list comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Stack ( list ) :
     
        def pops(self,n):
            '''pops the n first elements'''
            res = self[:n]
            self = self[n:]
            print self
            return res
     
        def push (self,vals):
            '''pushes vals at the head (vals must be a list)'''
            self = vals + self
            print self
    et pour une raison que je ne m'explique pas, les méthodes sont sans effet (self reste inchangé en sortie de méthode) alors que les print affichent bien ce que j'attends...
    Comme si self était restauré à la sortie.

    Quelqu'un y comprend quelque chose ?
    Comment obtenir une classe qui fait ce que je veux ?

    Merci d'avance

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    bonsoir,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Stack(list):
       def push(self, vals):
          for val in vals:
             self.insert(0,val)
       def pops(self, n):
             return [self.pop(0) for i in xrange(n)]
    c'est quelque chose comme ça que tu souhaite obtenir ?

    (on ne peut pas réaffecter self)

  3. #3
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Génial !!

    c'est ça !
    à un reversed près :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        def push(self, vals):
            for val in reversed( vals ):
                self.insert(0,val)
    Ça me rappelle le this du c++...

    Merci

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    je crois que c'est exactement la même chose que le this du c++

    attention cependant, les insert(0,...) et pop(0) d'une liste sont O(n) alors que le append(...) et le pop() sont en O(1). je ne sais pas si c'est gênant pour toi

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    C’est bien aussi de comprendre la cause des problèmes. Comparer:


    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
    class Stack ( list ) :
     
        def pops(self,n):
            '''pops the n first elements'''
            res = self[:n]
            self = self[n:]
            print '  res   ',id(res),res
            print '  self  ',id(self),self
            return res
     
        def push (self,vals):
            print '  self  ',id(self),self
            '''pushes vals at the head (vals must be a list)'''
            self = vals + self
            print '  self  ',id(self),self
     
     
    a = Stack()
    print 'new a ',id(a),a
     
    print '\na.push([2,3])'
    a.push([2,3])
    print 'a       ',id(a),a
     
    print '\na.push([7,8,34,56])'
    a.push([7,8,34,56])
    print 'a       ',id(a),a
     
    print '\na.pops(3)'
    a.pops(3)
    print 'a       ',id(a),a
    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
    new a  17505136 []
     
    a.push([2,3])
      self   17505136 []
      self   17540880 [2, 3]
    a        17505136 []
     
    a.push([7,8,34,56])
      self   17505136 []
      self   9917144 [7, 8, 34, 56]
    a        17505136 []
     
    a.pops(3)
      res    17541800 []
      self   9917144 []
    a        17505136 []


    et


    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
    class Stack ( list ) :
     
        def pops(self,n):
            '''pops the n first elements'''
            res = self[0:n]
            self[0:n] = []
            print '  res   ',id(res),res
            print '  self  ',id(self),self
            return res
     
        def push (self,vals):
            print '  self  ',id(self),self
            '''pushes vals at the head (vals must be a list)'''
            self[0:0] = vals
            print '  self  ',id(self),self
     
     
     
    a = Stack()
    print 'new a =',id(a),a
     
    print '\na.push([2,3])'
    a.push([2,3])
    print 'a       ',id(a),a
     
    print '\na.push([7,8,34,56])'
    a.push([7,8,34,56])
    print 'a       ',id(a),a
     
    print '\na.pops(3)'
    a.pops(3)
    print 'a       ',id(a),a
    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
    new a = 17505136 []
     
    a.push([2,3])
      self   17505136 []
      self   17505136 [2, 3]
    a        17505136 [2, 3]
     
    a.push([7,8,34,56])
      self   17505136 [2, 3]
      self   17505136 [7, 8, 34, 56, 2, 3]
    a        17505136 [7, 8, 34, 56, 2, 3]
     
    a.pops(3)
      res    17514744 [7, 8, 34]
      self   17505136 [56, 2, 3]
    a        17505136 [56, 2, 3]





    self[n:] crée un nouvel objet, c’est à dire à un emplacement mémoire différent

    self = self[n:] déplace l’étiquette self de l’objet local self (c’est à dire l’objet de type Stack traité) sur ce nouvel objet: l’objet de type Stack n’est absolument pas touché





    de même vals + self n’est pas une modification en place, cela crée un nouvel objet, à une adresse différente

    self = vals + self déplace l’étiquette self de l’objet de type Stack traité sur le nouvel objet





    Par contre ,
    self[0:n] = [] et self[0:0] = vals sont des opérations en place,c’est à dire qui changent les éléments de la liste sans toucher à sa localisation.

  6. #6
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Merci de toutes ces explications !

    Je me doutais un peu que c'était ce genre de problème liés à l'implémentation même de python.

    --> C'est justement ce qui me gène un peu avec les langages évolués qui mâchent tout le boulot : on a l'impression d'être détaché des détails d'implémentation mais de temps en temps on tombe sur ce genre d'os qui obligent à savoir ce qui se passe dans les tripes de l'interpréteur.

    Rien n'empêche une autre implémentation (sous un autre OS/plateforme/matériel) d'avoir un comportement différent.
    --> Y aurait-il une norme au niveau des choix d'implémentation ?

    Au moins en C++, this est const et on sait tout de suite qu'on ne peut pas y toucher.

    Mais bon... ça reste un langage très agréable !

  7. #7
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    oui, il y a quelques trucs un peu pénibles mais comparativement moins que dans des langages de plus bas niveau

  8. #8
    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
    Citation Envoyé par sopsag Voir le message
    Je me doutais un peu que c'était ce genre de problème liés à l'implémentation même de python.
    Le fait que self se comporte comme il le fait, ce n'est pas lié à l'implémentation, c'est la sémantique même du langage.

    Rien n'empêche une autre implémentation (sous un autre OS/plateforme/matériel) d'avoir un comportement différent.
    --> Y aurait-il une norme au niveau des choix d'implémentation ?
    Non. Une autre implémentation doit respecter la même sémantique, sinon ce n'est pas du python, mais au mieux un langage apparenté. Il n'y a pas à ma connaissance de standard publié qui définisse python, la norme de facto est l'implémentation de CPython. Un certain nombre de points sont documentés dans les PEP.

    Au moins en C++, this est const et on sait tout de suite qu'on ne peut pas y toucher.
    Au sein de la méthode, self est un argument comme un autre; il n'a rien de magique. D'ailleurs rien ne t'oblige à l'appeler "self", c'est juste une convention (mais que tout le monde utilise donc il est fortement déconseillé de ne pas la suivre).

    Python n'est pas un langage compliqué, mais il n'est pas extrêmement simple non plus. On a plus vite fait le tour d'un langage comme le C, par exemple, que de Python, dans le sens où il y a moins de concepts à appréhender en C. Ce qui ne veut pas dire qu'il est plus facile de programmer en C qu'en Python.

  9. #9
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Salut,
    Je ne sais trop ce que tu entends par:
    Citation Envoyé par dividee Voir le message
    Non. Une autre implémentation doit respecter la même sémantique, sinon ce n'est pas du python, mais au mieux un langage apparenté. Il n'y a pas à ma connaissance de standard publié qui définisse python, la norme de facto est l'implémentation de CPython.
    The Python Language Reference me semble répondre aux questions concernant la définition de ce qu'est le langage Python. Même si ce n'est pas un "standard" au sens ANSI/IEEE/...
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre confirmé Avatar de sopsag
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 224
    Par défaut
    Citation Envoyé par dividee Voir le message
    Ce qui ne veut pas dire qu'il est plus facile de programmer en C qu'en Python.
    Ce que je voulais dire, c'est qu'on présente Python comme un langage très intuitif et qui n'oblige pas à comprendre le fonctionnement sous-jacent.
    En C, pour maîtriser la notion de pointeurs, il faut en connaître un minimum sur le fonctionnement d'un allocateur, d'un tas, d'une pile etc. Et si on veut porter son code, on est confronté aux problèmes d'endianness, d'alignement en mémoire, et j'en passe. Bref !
    En Python, on est censé est débarrassé de toutes ces questions, et ce qu'il faut savoir pour programmer semble assez éloigné du fonctionnement de la machine.

    Or, de temps en temps, on tombe sur des détails comme ça qui laissent apparaître des choix d'implémentation (standards ou pas, ce n'est pas la question).
    Ce qui fait que quand on initie quelqu'un à Python, et si on ne veut pas se lancer dans une digression interminable, on est parfois obligé de dire : "c'est comme ça, ne cherche pas à comprendre..."

    Donc, (pour retomber sur mes pieds) le fait que, dans le corps d'une méthode, self se comporte comme une variable ordinaire (son affectation ne provoquant aucune erreur), mais qu'en sortie on retrouve son ancienne valeur, me paraît assez en contradiction avec l'intuitivité prêtée à Python.

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Salut

    Ce que je voulais dire, c'est qu'on présente Python comme un langage très intuitif et qui n'oblige pas à comprendre le fonctionnement sous-jacent.
    Ce genre de facilité est sans doute très vrai pour ceux qui utilisent Python pour réaliser de "l'intégration": on crée des ponts entre différents sous-systèmes via des API de haut niveau écrites en Python.
    Les sous-systèmes utilisés sont assez structurants côté codage/style pour Python reste assez dormant et son utilisation plutôt ludique.
    Note: un script réalisé pour faire de l'exploitation entre dans ce cadre.

    Maintenant, utilisez Python comme un langage de POO similaire à C++ ou Java... Il sera intuitif avec quelques années d'expérience en C++ ou en Java, mais le débutant aura quand même à faire un apprentissage assez long.

    Et Python est-il un bon choix comme "premier langage" pour apprendre la POO?
    - W
    PS: La programmation reste un métier avec des bases compliquées.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    Citation Envoyé par sopsag Voir le message
    Donc, (pour retomber sur mes pieds) le fait que, dans le corps d'une méthode, self se comporte comme une variable ordinaire (son affectation ne provoquant aucune erreur), mais qu'en sortie on retrouve son ancienne valeur, me paraît assez en contradiction avec l'intuitivité prêtée à Python.
    bonsoir,

    ben non, c'est logique. ce n'est pas un comportement en contradiction avec le reste de Python.

    l'opération d'affectation crée un nom, une étiquette. l'affectation en python n'a rien à voir avec l'affectation dans un langage comme le C++ (qui peut être surchargée).

    self est un nom (non réservé qui plus est) "pointant" vers l'emplacement mémoire de l'objet. en affectant self à quelque chose d'autre, l'étiquette se déplace vers un autre emplacement mémoire. l'emplacement mémoire de l'objet conserve son état.

    et donc à la sortie de la fonction, l'objet reste inchangé.

    il n'y a pas de magie noire là dessous, mais il faut savoir ce que fait l'opération d'affectation. ça fait partie des bases du langages

    je me faisais moi même la même remarque au début. je me disais que Python c'était facile alors j'ai "sauté" les premiers chapitres des bouquins et commencé à coder. Et puis au bout d'un moment, je me suis rendu compte qu'il y avait des trucs pas intuitifs et en cherchant, je me suis rendu compte que j'avais rien compris en fait. J'ai repris les bases (simples, je persiste) et maintenant, ça roule

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

Discussions similaires

  1. Classe dérivée de 'list' avec un membre en plus.
    Par sopsag dans le forum Général Python
    Réponses: 7
    Dernier message: 04/08/2010, 18h41
  2. destructeur d'une classe dérivée du type list
    Par Haze. dans le forum Général Python
    Réponses: 2
    Dernier message: 19/11/2007, 01h11
  3. Réponses: 4
    Dernier message: 20/11/2005, 05h48
  4. [MFC] CArray et classe dérivée?
    Par TigreRouge dans le forum MFC
    Réponses: 14
    Dernier message: 02/08/2005, 22h45
  5. Déterminer le type d'une class dérivée
    Par LDDL dans le forum MFC
    Réponses: 3
    Dernier message: 10/12/2004, 17h36

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