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

时间:2017-01-08 15:48:19

标签: python setattribute setattr

我的智慧结束了。 无法找到任何有助于此的内容。

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

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

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

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

6 个答案:

答案 0 :(得分:5)

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

在更多实施级别上,调用getattr / setattr实际上是data.__getattr__("foo")的简写,因为dict使用__getitem__而不是__getattr__函数调用失败。

因此,没有办法使用通用属性函数设置(或得到那个)dict的项目。

然而,您可以创建支持该操作的自定义dict类(虽然我不推荐它):

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"))

答案 1 :(得分:1)

您可以直接指定dict值,不需要setattr()。

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

答案 2 :(得分:1)

' SETATTR()'是指别的东西。当您写setattr(dta, 'type', "Steve")时,您尝试访问字段dta.type,dict类没有属性type,因此会出错。

dict_object['key']是一个完全不同的东西,它应该如何访问dict成员。

有关settatr()Here

的更多信息

答案 3 :(得分:1)

字典是subscriptable,关键:值对是项而不是属性。

使用下标表示法访问项目:

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

答案 4 :(得分:1)

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__dict__ obj中设置了一个项目,并且可以使用.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'

我使用字典索引表示法向dict添加项目:

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

如果__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

答案 5 :(得分:0)

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

  

这是getattr()的对应物。参数是对象,   一个字符串和一个任意值。该字符串可以命名现有的   属性或新属性。该函数将值赋给   属性,只要对象允许它

OBJECT不是DICTIONARY。我可能会将我的JS工作(语法)与我总是同时编写的Python代码混淆

因此错误消息令人困惑:

  

AttributeError:'dict'对象没有属性'type'

应该更像是:

  

'setattr()用于不是字典的对象

谢谢大家。