1

Salut,
J'utilise PyQt pour développer (rapidement normalement) une petite application, et je bloque sur un petit truc, je me demande si le comportement obtenu est normal ou si c'est un bug. Qu'en pensez-vous ?
class PyQtObject:
  def __init__(self):
    pass
  def __setattr__(self, name, value):
    self.__dict__[name] = value
    print self.__dict__

class MyPyQtObject (PyQtObject):
  def __init__(self):
    PyQtObject.__init__(self)
    self.attr = "value"

i = MyPyQtObject()
i.attr2 = "value2"

Bon, rien de compliqué, je surcharge juste __setattr__ pour ensuite pouvoir un peu mieux contrôler ce qui se passe lors d'une affectation.
Quand j'exécute le code, j'obtiens la sortie (attendue) suivante :
$ python Test.py
{'attr': 'value'}
{'attr2': 'value2', 'attr': 'value'}


Mais maintenant, si je fais dériver PyQtObject de QtCore.QObject comme ci-dessous :
class PyQtObject (QtCore.QObject):
  def __init__(self):
    QtCore.QObject.__init__(self)
  def __setattr__(self, name, value):
    self.__dict__[name] = value
    print self.__dict__

(sans changer le reste du code)
Voici la sortie que j'obtiens :
$ python Test.py
{}
{}


Pourquoi __dict__ reste-t-il tout le temps vide ?
Qu'est-ce que j'ai mal fait ?
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

2

Mouais, ça ne vous inspire pas vraiment... grin
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

3

C'est parce que PyQt (ou plutôt SIP) bidouille __dict__:
http://www.riverbankcomputing.com/Docs/PyQt4/pyqt4ref.html#super-and-pyqt-classes
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

4

OK, mais je ne comprends pas comment je peux résoudre le problème (je dois "référencer" les attributs pour ne pas qu'ils provoquent d'exception AttributeError ? C'est-à-dire, "référencer" ?).
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

5

Je pense que tu ne peux pas toucher à __dict__ de cette manière sur un objet SIP, tout simplement. Un objet SIP est un objet C++ wrappé, pas un objet Python natif, c'est normal qu'il ne se comporte pas tout à fait de la même manière.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

6

Rah c'est dommage, ça me permettait d'obtenir un modèle super pratique : en émettant un signal à chaque appel de __setattr__ (donc à chaque ligne de code de ce type : "objet.attribut = valeur"), ça me permettait d'avoir un code très très simple pour gérer mes objets et en même temps de mettre au courant l'interface graphique à chaque fois que les objets sont modifiés.
Là je vais être obligé de faire des :
class MonObjet (QtCore.QObject):
  def __init__(self):
    QtCore.QObject.__init__(self)
  def setAttribut1(self, value):
    self.attribut1 = value
    self.emit(QtCore.SIGNAL("attribut1Changed"), value)

sick

Pourquoi la vie est-elle moche comme ça ?
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

7

ben c'est un setter, et c'est fait pour, non?

la capture des affectations je sais pas si c'est très répandu en dehors de python et php.

8

Ouais, mais le but c'était de ne pas passer trois heures à pisser du code bête qu'il faudra encore débugger ensuite.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

9

Je te signale que si l'attribut est modifié par Qt, ton setter ne sera pas appelé parce que les setters ne sont pas virtuels dans les classes C++, donc tu as beau les surcharger, Qt appellera toujours son implémentation C++.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

10

tritop sad
À quand un bon langage objet permettant de créer des GUI correctement ?
Il ne reste plus que Java là, mais ça reste un peu lourd...
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

11

C'est pour des raisons de performances. D'ailleurs, pas mal de setters étaient virtuels dans Qt 3 et ne le sont plus dans Qt 4: http://doc.trolltech.com/4.3/porting4.html#virtual-functions.
Le "tout est virtuel" est bien une des raisons pour lesquelles le Java rame.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

12

ah oui? parce que ça appelle la méthode du type de l'objet runtime?

13

Et surtout il faut au moins une indirection pour ça, normalement 3 (déréférencer la classe pour avoir la vtable, déréférencer la vtable pour avoir le pointeur de fonction, sauter en le pointeur déréférencé), et je ne parle même pas du cas où l'implémentation est en Python là.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

14

Bon en fait, il semblerait qu'au lieu de faire :
self.__dict__[name] = value
Je devrais faire :
QtCore.QObject.__setattr__(self, name, value)
(je n'ai pas encore testé je ferai ça dès que j'aurais du temps, c'est-à-dire pas avant une bonne semaine...)
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »