为什么类__dict__是mappingproxy?

时间:2015-09-22 15:08:59

标签: python class python-3.x python-internals

我想知道为什么课程__dict__mappingproxy,但实例__dict__只是普通dict

>>> class A:
...     pass

>>> a = A()
>>> type(a.__dict__)
<class 'dict'>
>>> type(A.__dict__)
<class 'mappingproxy'>

3 个答案:

答案 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。有一个issuedictproxy添加为公共内置类型。

  • Python 3.3:添加了上述的<class 'mappingproxy'>类型。