Python setattr() 找不到明显存在的属性

Python setattr() can't find attribute that obviously exists

我已经无计可施了。 找不到任何其他对此有帮助的东西。

dta = {'type': "", 'content': ""}
print dta

>>>{'content': '', 'type': ''}

setattr(dta, 'type', "Steve")

>>>AttributeError: 'dict' object has no attribute 'type'

可以直接给dict赋值,不需要setattr()

dta = {'type': "", 'content': ""}
dta["type"] = "Steve"

Python 的字典不是 JS 对象。当你创建一个字典时,你并不是在创建一个动态对象,你可以像在 JS 中那样在运行时更改其属性。相反,字典知道如何存储键和值对,并通过覆盖运算符 [] (def __getitem__(self, key)).

来实现。

在更具体的实施层面上 - 调用 getattr / setattr 实际上是 data.__getattr__("foo") 的 shorthand,因为 dict 使用 __getitem____getattr__ 相反,函数调用失败。

因此,无法使用通用属性函数设置(或获取)dict 的项目。

但是,您可以创建支持该操作的自定义字典 ​​class(尽管我不推荐):

class AttrDict(dict):
    def __init__(self):
        dict.__init__(self)

    # Override getattr and setattr so that they return the values of getitem / setitem
    def __setattr__(self, name, value):
        self[name] = value

    def __getattr__(self, name):
        return self[name]

data = AttrDict()
data["foo"] = "bar"
print(getattr(data, "foo"))

'setattr()'指的是别的东西。当你写 setattr(dta, 'type', "Steve") 时你试图访问字段 dta.type,dict class 没有属性 type,所以它给出了一个错误。

dict_object['key'] 是完全不同的东西,它是访问字典成员的方式。

更多关于 settatr() Here

docs.python.org/2/library/functions.html#setattr

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

OBJECT 不是字典。而且我可能将我的 JS 工作(语法)与我总是同时编写的 Python 代码混淆了

因此错误信息令人困惑:

AttributeError: 'dict' object has no attribute 'type'

应该更像是:

'setattr() is for objects not dictionaries'

.

谢谢大家

词典是 subscriptable,key:value 对是项而不是属性。

使用下标符号访问项目:

>>> d = {'a':1, 'b':2}
>>> d['a']
1

Attributes are accessed using dot notation

>>> d.a
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    d.a
AttributeError: 'dict' object has no attribute 'a'

operator.itemgetter 类似于 getattr:

>>> import operator
>>> bee = operator.itemgetter('b')
>>> bee(d)
2
>>>  

>>> hasattr(d, '__getitem__')
True
>>> hasattr(d, '__getattr__')
False
>>> 

setattr 不适用于字典,因为它没有 __dict__

我可以做一个简单的class和实例:

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

setattrobj__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}

字典 class 继承自 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 returns 此示例中的另一个错误。

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

所以错误信息是由dictclass决定的,而不是setattr.

即使 __dict_- 的实例在 setattr 被错误使用时也可能引发错误。例如,数字不是有效的属性名称:

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