Jos*_*uis 60 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'>
Run Code Online (Sandbox Code Playgroud)
Ray*_*ger 65
这有助于解释器确保类级属性和方法的键只能是字符串.
在其他地方,Python是一种"同意成人语言",这意味着用户可以公开和改变对象的序列.但是,对于类的类级别属性和方法,如果我们可以保证键是字符串,我们可以简化和加速类级别的属性和方法查找的常见案例代码.特别是,通过假设类dict键是字符串,简化了新样式类的__mro__搜索逻辑并加快了速度.
pro*_*sti 12
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
Run Code Online (Sandbox Code Playgroud)
mappingproxy 从 Python 3.3 开始。以下代码显示了 dict 类型:
class C:pass
ci=C()
print(type(C.__dict__)) #<class 'mappingproxy'>
print(type(ci.__dict__)) #<class 'dict'>
Run Code Online (Sandbox Code Playgroud)
因为Python 3.3mappingproxy类型已改名为从dictproxy。关于这个话题有一个有趣的讨论。
找到这种类型的文档有点困难,但是vars方法的文档完美地描述了这一点(尽管有一段时间没有记录):
模块和实例等对象具有可更新的
__dict__属性;但是,其他对象可能对其__dict__属性有写限制 (例如,类使用 types.MappingProxyType 来防止直接更新字典)。
如果您需要分配一个新的类属性,您可以使用setattr. 值得注意的mappingproxy是,JSON 不是可序列化的,请查看问题以了解原因。
这种类型的历史也很有趣:
type(A.__dict__)返回<type 'dict'>as type(dict()),并且可以通过 分配新属性__dict__,例如A.__dict__['foo'] = 'bar'。type(A.__dict__)返回<class 'dict_proxy'>,引入区别。尝试分配一个新的属性会给TypeError. 曾尝试将其添加dictproxy为公共内置类型。<class 'mappingproxy'>类型。