Unexpected behavior of read only attributes and super

Samuel M. Smith smithsm at samuelsmith.org
Tue Dec 6 13:25:13 EST 2005


I have been playing around with a subclass of dict wrt a recipe for  
setting dict items using attribute syntax.
The dict class has some read only attributes that generate an  
exception if I try to assign a value to them.
I wanted to trap for this exception in a subclass using super but it  
doesn't happen.
I have read Guido's tutorial on new style classes and Shalabh's  
tuturial on new style attributes and methods, and thought
I understood what super was doing. But there is no discussion on read  
only attributes and their associated magic.

It seems to me that there is some undocumented magic that does not  
make sense to me.

for example

d = dict()
d.__iter__ returns
<method-wrapper object at 0x260a10>

If I try to assign a value to d.__iter__
d.__iter__ = False
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
AttributeError: 'dict' object attribute '__iter__' is read-only

If I use the setattr method, I get the exception also as expected

d.__setattr__('__iter__', False)
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
AttributeError: 'dict' object attribute '__iter__' is read-only



but if I subclass and use super

class SD(dict):
    pass

s = SD()
s.__iter__ returns
<method-wrapper object at 0x260a10>
so the object s has this attribute
hasattr(s,'__iter__') also returns
True

but s.__dict__ is empty at this stage so s has inherited this  
attribute as a method



so far so good.
If I assign a value
s.__iter__ = False

it lets me but adds the attribute to s.__dict__ thereby shadowing the  
method, no surprises yet
s.__dict__ returns
{'__iter__': False}

but I want to know if the attribute is a read only attribute of the  
super class so that I don't shadow it
in the subclass. So I start over and try

s = SD()
super(SD,s).__setattr__('__iter__', True)

Expecting to get the ReadOnly exception but I don't get the exception.
Instead the attribute is added to s.__dict__.
s.__dict__ returns
{'__iter__': True}

Shouldn't the super __setattr__ call be using the same code as the  
direct call to dict's __setattr__
and therefore produce an exception?









More information about the Python-list mailing list