problems with __getattr__ & __setattr__
Tim Evans
tre17 at student.canterbury.ac.nz
Tue Nov 16 21:37:01 EST 1999
ScherBi at BAM.com writes:
> I am having trouble using __getattr__ and __setattr__ in some classes. I've
> boiled it down to the code below.
> It dumps core under 1.5.2 on Linux or WinNT.
>
> I think maybe it's looping, if so, how does one go about doing this?
> (I'm assuming it's clear enough what I'm trying to do.)
>
> If I comment out the __gettattr__ operation, it doesn't dump core. Instead
> I get an AttributeError: eggs raised at the 'self.eggs[key] = value' call in
> __setattr__. This is what leads me to belive there's something circular
> going on here.
>
>
> Thanks,
> Bill
>
> --------------------------------------------
> class spam:
>
> def __init__(self):
> self.eggs = {}
>
> def __getattr__(self, key):
> try:
> return self.eggs[key]
> except:
> raise
>
> def __setattr__(self, key, value):
> try:
> self.eggs[key] = value
> return 0
> except:
> raise
>
> if __name__ == '__main__':
>
> s = spam()
> print 'instance of spam created.'
> -----------------------------------------------
I think I see the problem here. In __init__ you try to set an
attribute (self.eggs = {}), which will cause __setattr__ to be called.
In __setattr__ you get the eggs attribute, which does not exist, so
the attribute access is passed to __getattr__.
In __getattr__ you access the eggs attribute again, which as it does
not exist will again be passed to __getattr__, causing an infinite
loop.
To demonstrate this add a print statement at the start of each method
that prints the name of the method. The result is:
-----------------------------
% python broken.py
__init__
__setattr__
__getattr__
__getattr__
__getattr__
__getattr__
__getattr__
__getattr__
__getattr__
...
zsh: segmentation fault python broken.py
-----------------------------
To solve this problem I would recommend not using __getattr__ and
__setattr__ unless you really need it. If you don't want to use
s.eggs['foo'] then you could define __setitem__ and __getitem__ to
shorten this to s['foo']
--
Tim Evans
More information about the Python-list
mailing list