[PyQt] Subclassing QObject and overloading __setattr__

Phil Thompson phil at riverbankcomputing.com
Tue Jan 29 17:24:25 GMT 2008


On Saturday 26 January 2008, Julien Richard-Foy wrote:
> Here is the content of Test.py :
>
> 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"
>
> When I execute this script, I get this (expected) output :
> $ python Test.py
> {'attr': 'value'}
> {'attr2': 'value2', 'attr': 'value'}
>
>
> And now if I declare PyQtObject as a child class from QtCore.QObject as
> there :
>
> class PyQtObject (QtCore.QObject):
>   def __init__(self):
>     QtCore.QObject.__init__(self)
>   def __setattr__(self, name, value):
>     self.__dict__[name] = value
>     print self.__dict__
>
> Here is what I get :
> $ python Test.py
> {}
> {}
>
> Is this the expected behavior ? Why is __dict__ still empty ?

It's a feature of the lazy attribute handling that SIP implements.  __dict__ 
is treated specially (so that dir() works) with the result that (if a 
__dict__ attribute doesn't already exist) a temporary dict is returned. This 
is used to save the attribute, but isn't itself saved.

This implementation orginates from the Python v1.5.2 days and it may well be 
improved using descriptors. However I'm not willing to mess with it at the 
moment.

If you want to set the attribute in the reimplementation then call the base 
implementation as you would do with anything else, ie. replace...

    self.__dict__[name] = value

...with...

    QtCore.QObject.__setattr__(self, name, value)

Phil


More information about the PyQt mailing list