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'
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不适用于字典,因为它没有__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)