我想知道为什么课程__dict__
是mappingproxy
,但实例__dict__
只是普通dict
>>> class A:
... pass
>>> a = A()
>>> type(a.__dict__)
<class 'dict'>
>>> type(A.__dict__)
<class 'mappingproxy'>
答案 0 :(得分:56)
这有助于解释器确保类级属性和方法的键只能是字符串。
在其他地方,Python是一种同意成人语言&#34;,这意味着用户可以公开和改变对象的词条。但是,对于类的类级属性和方法,如果我们可以保证键是字符串,我们可以简化和加速类级别的属性和方法查找的常见案例代码。特别是,通过假设类dict键是字符串来简化和加速新样式类的__mro__搜索逻辑。
答案 1 :(得分:2)
mappingproxy只是没有__setattr__
方法的字典。
您可以签出并参考此代码。
from types import MappingProxyType
d={'key': "value"}
m = MappingProxyType(d)
print(type(m)) # <class 'mappingproxy'>
m['key']='new' #TypeError: 'mappingproxy' object does not support item assignment
mappingproxy自Python 3.3起。以下代码显示了dict类型:
class C:pass
ci=C()
print(type(C.__dict__)) #<class 'mappingproxy'>
print(type(ci.__dict__)) #<class 'dict'>
答案 2 :(得分:1)
由于Python 3.3 mappingproxy
类型是dictproxy
的{{3}}类型。这个主题有一个有趣的renamed。
很难找到这种类型的文档,但是discussion方法的文档对此进行了很好的描述(尽管vars有一段时间):
对象(例如模块和实例)具有可更新的
__dict__
属性;但是,其他对象可能对其具有写限制__dict__
属性(例如,类使用type.MappingProxyType来防止直接字典更新)。
如果您需要wasn't documented的新类属性,则可以使用setattr
。值得注意的是,mappingproxy
不可JSON序列化,请查看assign以了解原因。
这种类型的历史也很有趣:
Python 2.7: type(A.__dict__)
返回<type 'dict'>
为type(dict())
,并且可以通过__dict__
分配新属性,例如
A.__dict__['foo'] = 'bar'
。
Python 3.0-3.2: type(A.__dict__)
返回<class 'dict_proxy'>
,现在区别更加清楚了。尝试分配新的属性将得到TypeError
。有一个issue将dictproxy
添加为公共内置类型。
<class 'mappingproxy'>
类型。