setattr 不适用于字典,因为它没有__dict__。
我可以创建一个简单的类和实例:
In [88]: class Obj(object):
...: pass
...:
In [89]: ob = Obj()
In [90]: ob.__dict__
Out[90]: {}
In [91]: setattr(ob,'test',34)
In [92]: ob.__dict__
Out[92]: {'test': 34}
In [95]: ob.test
Out[95]: 34
setattr 在obj 的__dict__ 中设置一个项目,结果属性可以通过.test 语法访问。
但是dict 对象没有__dict__。
In [96]: dd={1:2, 3:4}
In [97]: dd.__dict__
AttributeError: 'dict' object has no attribute '__dict__'
In [98]: setattr(dd, 'test', 34)
AttributeError: 'dict' object has no attribute 'test'
我使用字典索引符号将项目添加到字典:
In [99]: dd['test'] = 34
In [100]: dd
Out[100]: {1: 2, 3: 4, 'test': 34}
字典类继承自object,但不会给每个实例一个__dict__。因此setattr 没有什么可操作的。
如果由于某种原因[]= 语法很尴尬,您可以将operator.setitem 用作函数:
In [108]: operator.setitem?
Docstring: setitem(a, b, c) -- Same as a[b] = c.
Type: builtin_function_or_method
In [109]: operator.setitem(dd, 'test', 23)
In [110]: dd
Out[110]: {1: 2, 3: 4, 'test': 23}
或者使用__setitem__方法
In [111]: dd.__setitem__('test', 1)
In [112]: dd
Out[112]: {1: 2, 3: 4, 'test': 1}
实际上,字典确实有属性。例如,它的.get 方法可以用getattr 获取。 setattr 在此示例中返回不同的错误。
In [119]: getattr(dd,'get')
Out[119]: <function dict.get>
In [120]: setattr(dd,'get',dict.get)
...
AttributeError: 'dict' object attribute 'get' is read-only
没有__dict__,我们无法向字典添加属性。许多(如果不是全部)现有属性是只读的。不知道字典有没有可以改变的属性。
其实字典就是object:
In [121]: isinstance(dd,dict)
Out[121]: True
In [122]: isinstance(dd,object)
Out[122]: True
我刚刚导入了defaultdict。它也缺少__dict__。但我可以使用setattr(ddd,'default_factory', int)。我认为no attribute是当属性不存在时正确的错误信息,它不能添加新的。
==============
我必须仔细检查这方面的文档,但我认为 setattr(dd,...) 代表 dd.__setattr__(...)。
In [168]: dd.__setattr__('test',1)
...
AttributeError: 'dict' object has no attribute 'test'
In [169]: dd.__setattr__('get',None)
...
AttributeError: 'dict' object attribute 'get' is read-only
所以错误信息是由dict类确定的,而不是setattr。
如果setattr 使用错误,即使具有__dict_- 的实例也可能引发错误。例如,数字不是有效的属性名称:
In [171]: setattr(ob, 123, 'a')
....
TypeError: attribute name must be string, not 'int'
但是setattr可以设置不能用.语法访问的属性:
In [172]: setattr(ob, 'a#re',1)
In [174]: ob.a#re
...
AttributeError: 'Obj' object has no attribute 'a'
In [175]: getattr(ob, 'a#re')
Out[175]: 1
vars() 是访问实例的__dict__ 的另一种方式:
In [179]: vars(dd)
...
TypeError: vars() argument must have __dict__ attribute