[Tutor] setattr question

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Mon, 18 Feb 2002 11:39:48 -0800 (PST)


On Mon, 18 Feb 2002, Brad Reisfeld wrote:

> I have a class with many properties that are dictionaries. I am trying
> to set the values of these properties via setattr, but am having no
> luck.
> 
> I thought that since 'setattr(object, name, value)' should be the same as
> 'object.name = value', the following would work:
> 
> >>> class settest:
> ... 	def __init__(self):
> ... 		self.foo = {'prop1': 123, 'prop2': 456}
> ... 		return
> ...
> >>> m = settest()
> >>> m.foo['prop1'] = 987
> >>> m.foo
> {'prop2': 456, 'prop1': 987}
> >>> setattr(m,foo['prop2'],654)
> Traceback (most recent call last):
>   File "<interactive input>", line 1, in ?
> NameError: name 'foo' is not defined


Ah!  We can still do it like this:

    getattr(m, 'foo')['prop2'] = 654



> >>> setattr(m.foo,'prop2',654)
> Traceback (most recent call last):
>   File "<interactive input>", line 1, in ?
> TypeError: object has read-only attributes
>
> What is the proper way to set values in an object's property dictionary via
> setattr? Is this possible?


Hmmm! This is a weird one; I would have expected this to work.  Let me
check the documentation:


"""
setattr(object, name, value)
This is the counterpart of getattr(). The arguments are an object, a
string and an arbitrary value. The string may name an existing attribute
or a new attribute. The function assigns the value to the attribute,
provided the object allows it. For example, setattr(x, 'foobar', 123) is
equivalent to x.foobar = 123.
"""

Ah; that probably means that getattr() and setattr() don't work on
dictionaries, since they use indexing [] to grab at values.


I don't know if old-style dictionaries allow us to modify their
attributes; perhaps a new style dictionary in Python 2.2 will work.  Let's
try it:


### The following is in a Python 2.2 interpreter; I don't think this will
### work on older Pythons.  Sorry!
>>> class MyDict(dict): pass
... 
>>> d = MyDict({'hello': 42})
>>> d
{'hello': 42}
>>> setattr(d, 'name', 'tom riddle')
>>> d
{'hello': 42}
>>> d.name
'tom riddle'
###


Hope this helps!