Persistence de la valeur d'attributs d'une classe ?

Persistence de la valeur d'attributs d'une classe ? - Python - Programmation

Marsh Posté le 23-02-2006 à 20:34:34    

Salut,
 
je suis tombé sur un truc sur lequel j'ai mis pas mal de temps pour voir d'où venait le problème. Voici un exemple simple :
 - un module, nommé module_test pour l'occasion

Code :
  1. class table:
  2.    
  3.    name = None
  4.    attr = []
  5.    
  6.    def __init__(self, name):
  7.        self.name = name
  8.    
  9.    def attr_add(self, att):
  10.        self.attr.append(att)


 - et un petit jeu de test unitaire (noté la subtile inversion des noms des méthodes dans la classe TableTest [:icon14]) :

Code :
  1. #!/usr/bin/env python
  2.  
  3. import unittest
  4. import module_test
  5.  
  6. VERBOSITY = 2
  7.  
  8. class TableTest(unittest.TestCase):
  9.     
  10.     def test2(self):
  11.         t = module_test.table('t_test')
  12.         
  13.         self.assertEqual(t.name, 't_test')
  14.         self.assertEqual(t.attr, [])
  15.     
  16.     def test1(self):
  17.         t = module_test.table('t_test')
  18.         att = 'gni'
  19.         t.attr_add(att)
  20.         
  21.         self.assertEqual(len(t.attr), 1)
  22.         self.assertEqual(t.attr[0], att)
  23.  
  24.  
  25.  
  26. def suite():
  27.     suite = unittest.TestSuite()
  28.     suite.addTest(unittest.makeSuite(TableTest))
  29.     return suite
  30.  
  31.  
  32. if __name__ == "__main__":
  33.     unittest.TextTestRunner(verbosity=VERBOSITY).run(suite())


 
Bref, rien de transcendant [:petrus75]
Le problème est :


$ ./test_unit.py
test1 (__main__.TableTest) ... ok
test2 (__main__.TableTest) ... FAIL
 
======================================================================
FAIL: test2 (__main__.TableTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_unit.py", line 14, in test2
    self.assertEqual(t.attr, [])
  File "/usr/lib/python2.3/unittest.py", line 302, in failUnlessEqual
    raise self.failureException, \
AssertionError: ['gni'] != []
 
----------------------------------------------------------------------
Ran 2 tests in 0.001s
 
FAILED (failures=1)


 
Pourquoi je récupère cette valeur d'attribut pour table.attr ? [:pingouino]
Bien sur, si je rajoute un self.attr = [] dans le constructeur de table, le problème est résolu, mais j'aimerais comprendre ce qui se passe ...

Reply

Marsh Posté le 23-02-2006 à 20:34:34   

Reply

Marsh Posté le 23-02-2006 à 20:51:06    

Parce que attr est un attribut membre de la classe, donc il est construit à la création de la classe (== au parsing du fichier contenant la classe) et détruit à la destruction de l'objet classe (pas de l'instance de la classe, donc à la toute fin du script)
 
Donc ça se passe comme ça:
1. Le "module_test" est importé
2. L'objet "table" (a) (la classe donc) est crée
    a. table.name est instancé
    b. table.attr est instancé
3. L'objet TableTest est créé
4. Lancement des tests
6. Lancement du premier test
    a. Une instance de "table" est créée
    b. un élément est ajouté à table.attr, donc à un attribut de classe
    c. l'instance de "table" est détruite
7. Lancement du 2e test
    a. Une instance de "table" est créée
    b. Un test est effectué sur table.attr, donc l'attribut de classe
8. Les tests se terminent
9. L'objet (classe) TableTest est détruit
10. L'objet (classe) table est détruit, son attribut attr avec
11. Le script se termine
 
Quand tu effectues un accès sur un attribut d'une instance, Python recherche tout d'abord les attributs de l'instance, puis les attributs de la classe de l'instance [:spamafote]
 
a. Ce nom va complètement à l'encontre de la PEP8 au passage, et tu devrais hériter d'object, toujours hériter d'object ou d'une classe en héritant déjà


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 23-02-2006 à 21:00:39    

masklinn a écrit :

Parce que attr est un attribut membre de la classe, donc il est construit à la création de la classe (== au parsing du fichier contenant la classe) et détruit à la destruction de l'objet classe (pas de l'instance de la classe, donc à la toute fin du script)
 
Donc ça se passe comme ça:
1. Le "module_test" est importé
2. L'objet "table" (a) (la classe donc) est crée
    a. table.name est instancé
    b. table.attr est instancé
3. L'objet TableTest est créé
4. Lancement des tests
6. Lancement du premier test
    a. Une instance de "table" est créée
    b. un élément est ajouté à table.attr, donc à un attribut de classe
    c. l'instance de "table" est détruite
7. Lancement du 2e test
    a. Une instance de "table" est créée
    b. Un test est effectué sur table.attr, donc l'attribut de classe
8. Les tests se terminent
9. L'objet (classe) TableTest est détruit
10. L'objet (classe) table est détruit, son attribut attr avec
11. Le script se termine
 
Quand tu effectues un accès sur un attribut d'une instance, Python recherche tout d'abord les attributs de l'instance, puis les attributs de la classe de l'instance [:spamafote]


Ok, je voyais ça un peu comme ça. Donc, à priori, je peux laisser tomber la déclaration de mes attributs ici, et déplacer leur initialisation dans le constructeur ? (à part si je veux précisément ce comportement, ou si je leur donne une valeur dans le constructeur, comme pour name)

masklinn a écrit :


a. Ce nom va complètement à l'encontre de la PEP8 au passage, et tu devrais hériter d'object, toujours hériter d'object ou d'une classe en héritant déjà


Tout a fait, j'en ai déjà fait les frais, j'ai juste fais un test rapide pour voir si j'arrivais à reproduire ce truc :)

Reply

Marsh Posté le 23-02-2006 à 21:02:41    

multani a écrit :

Ok, je voyais ça un peu comme ça. Donc, à priori, je peux laisser tomber la déclaration de mes attributs ici, et déplacer leur initialisation dans le constructeur ? (à part si je veux précisément ce comportement, ou si je leur donne une valeur dans le constructeur, comme pour name)


Ben oui, si tu veux un attribut d'instance tu le définit en tant qu'attribut d'instance quoi [:spamafote]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 23-02-2006 à 21:08:37    

Ça roule [:datoune]
 
Merci :jap:

Reply

Marsh Posté le 23-02-2006 à 21:12:15    

J'avouerais par contre qu'au début je me suis également fait avoir une ou deux fois par le fait qu'on déclare un attribut de classe de cette manière [:aloy]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 23-02-2006 à 21:24:51    

On va dire que c'est des "restes" de C++ ou de C# [:petrus75]

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed