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

Ste*_*eve 0 python setattribute setattr

我的智慧结束了.找不到任何有助于此的内容.

dta = {'type': "", 'content': ""}
print dta
Run Code Online (Sandbox Code Playgroud)

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

setattr(dta, 'type', "Steve")
Run Code Online (Sandbox Code Playgroud)

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

Nik*_*off 5

Python的字典不是JS对象.创建dict时,您不会创建一个动态对象,其属性可以在运行时更改,就像在JS中一样.相反,字典知道如何存储键和值对,并通过重写operator [](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"))
Run Code Online (Sandbox Code Playgroud)

  • 不,不是。`setattr` 是一个内置函数,专门用于更改*对象属性*的值,而不是字典值。 (2认同)

hpa*_*ulj 5

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
Run Code Online (Sandbox Code Playgroud)

setattr__dict__of 中设置一个项目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'
Run Code Online (Sandbox Code Playgroud)

我使用字典索引符号向 dict 添加项目:

In [99]: dd['test'] = 34
In [100]: dd
Out[100]: {1: 2, 3: 4, 'test': 34}
Run Code Online (Sandbox Code Playgroud)

字典类继承自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}
Run Code Online (Sandbox Code Playgroud)

或者使用__setitem__方法

In [111]: dd.__setitem__('test', 1)
In [112]: dd
Out[112]: {1: 2, 3: 4, 'test': 1}
Run Code Online (Sandbox Code Playgroud)

实际上,字典确实具有属性。例如,它的.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
Run Code Online (Sandbox Code Playgroud)

没有 ,__dict__我们无法向字典添加属性。许多(如果不是全部)现有属性都是只读的。我不知道字典是否有可以更改的属性。

实际上字典是一个object

In [121]: isinstance(dd,dict)
Out[121]: True
In [122]: isinstance(dd,object)
Out[122]: True
Run Code Online (Sandbox Code Playgroud)

我刚导入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
Run Code Online (Sandbox Code Playgroud)

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

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

In [171]: setattr(ob, 123, 'a')
....
TypeError: attribute name must be string, not 'int'
Run Code Online (Sandbox Code Playgroud)

但是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
Run Code Online (Sandbox Code Playgroud)

vars()是另一种访问__dict__实例的方式:

In [179]: vars(dd)
 ...
TypeError: vars() argument must have __dict__ attribute
Run Code Online (Sandbox Code Playgroud)