Stef Mientki wrote: > hello, > > I tried to find an easy way to add properties (attributes) to a number > of different components. > So I wrote a class, from which all these components are derived. > By trial and error I created the code below, which now works, but > there is one thing I don't understand: > in the line indicated with "<<== 1" I'm not allowed to use > > for item in self.extra_getters : > > because it will result in an infinite recursion. > But in the line indicated with "<<== 2" , I am allowed ... > ... why is this allowed ??
When the instance is created self.extra_setters = {} in the __init__() method triggers self.__setattr__("extra_setters", {}) which executes for item in self.extra_setters: # ... in the __setattr__() method. Because at that point there is no extra_setters attribute self.__dict__["extra_setters"] fails and self.__getattr__("extra_setters") is used as a fallback. Now as __getattr__() contains a self.extra_getters attribute access and that attribute doesn't exist either this again triggers self.__getattr__("extra_getters") -- ad infinitum. By the way, looping over a dictionary destroys its key advantage, O(1) lookup. Use # untested if attr in self.extra_setters: self.extra_setters[attr](value) else: self.__dict__[attr] = value and something similar in __getattr__(). Peter > > thanks, > Stef Mientki > > > # *********************************************************************** > # *********************************************************************** > class _add_attribs ( object ) : > def __init__ ( self ) : > self.extra_setters = {} > self.extra_getters = {} > > def _add_attrib ( self, text, setter = None, getter = None ) : > if setter : > self.extra_setters [ text ] = setter > if getter : > self.extra_getters [ text ] = getter > > # ********************************************************* > # always called instead of the normal mechanism > # ********************************************************* > def __setattr__ ( self, attr, value ) : > for item in self.extra_setters : > if item == attr : > self.extra_setters [ item ] ( value ) > break > else : > self.__dict__[attr] = value > > # ********************************************************* > # only called when not found with the normal mechanism > # ********************************************************* > def __getattr__ ( self, attr ) : > try : > for item in self.__dict__['extra_getters'] : <<== 1 > if item == attr : > return self.extra_getters [ item ] ( ) <<== 2 > except : > return [] > # *********************************************************************** -- http://mail.python.org/mailman/listinfo/python-list