为什么 class __dict__ 是映射代理?
Why is a class __dict__ a mappingproxy?
我想知道为什么 class __dict__
是 mappingproxy
,而实例 __dict__
只是普通的 dict
>>> class A:
... pass
>>> a = A()
>>> type(a.__dict__)
<class 'dict'>
>>> type(A.__dict__)
<class 'mappingproxy'>
这有助于解释器确保 class 级属性和方法的键只能是字符串。
在其他地方,Python 是一个 "consenting adults language",这意味着对象的字典由用户公开和可变。但是,对于classes的class级属性和方法,如果能保证key是字符串,就可以简化和加速属性和方法查找的common case代码在 class 级。特别是,__mro__ 新式 classes 的搜索逻辑通过假设 class dict 键是字符串得到简化和加速。
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 开始。以下代码显示字典类型:
class C:pass
ci=C()
print(type(C.__dict__)) #<class 'mappingproxy'>
print(type(ci.__dict__)) #<class 'dict'>
自 Python 3.3 mappingproxy
类型 renamed from dictproxy
. There was an interesting discussion 关于此主题。
这个类型的文档有点难找,不过vars method describes this perfectly (though it wasn't documented找了一会儿的文档):
Objects such as modules and instances have an updateable __dict__
attribute; however, other objects may have write restrictions on their
__dict__
attributes (for example, classes use a types.MappingProxyType to prevent direct dictionary updates).
如果您需要assign a new class attribute you could use setattr
. It worth to note that mappingproxy
is not JSON serializable, check out the issue了解原因。
这个类型的历史也很有趣:
- Python 2.7:
type(A.__dict__)
returns <type 'dict'>
as type(dict())
,并且可以分配新的通过 __dict__
的属性,例如A.__dict__['foo'] = 'bar'
.
- Python 3.0 - 3.2:
type(A.__dict__)
returns <class 'dict_proxy'>
,区别介绍。尝试分配一个新属性会得到 TypeError
。有一个 attempt 添加 dictproxy
作为 public 内置类型。
- Python 3.3: 添加上述
<class 'mappingproxy'>
类型。
我想知道为什么 class __dict__
是 mappingproxy
,而实例 __dict__
只是普通的 dict
>>> class A:
... pass
>>> a = A()
>>> type(a.__dict__)
<class 'dict'>
>>> type(A.__dict__)
<class 'mappingproxy'>
这有助于解释器确保 class 级属性和方法的键只能是字符串。
在其他地方,Python 是一个 "consenting adults language",这意味着对象的字典由用户公开和可变。但是,对于classes的class级属性和方法,如果能保证key是字符串,就可以简化和加速属性和方法查找的common case代码在 class 级。特别是,__mro__ 新式 classes 的搜索逻辑通过假设 class dict 键是字符串得到简化和加速。
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 开始。以下代码显示字典类型:
class C:pass
ci=C()
print(type(C.__dict__)) #<class 'mappingproxy'>
print(type(ci.__dict__)) #<class 'dict'>
自 Python 3.3 mappingproxy
类型 renamed from dictproxy
. There was an interesting discussion 关于此主题。
这个类型的文档有点难找,不过vars method describes this perfectly (though it wasn't documented找了一会儿的文档):
Objects such as modules and instances have an updateable
__dict__
attribute; however, other objects may have write restrictions on their__dict__
attributes (for example, classes use a types.MappingProxyType to prevent direct dictionary updates).
如果您需要assign a new class attribute you could use setattr
. It worth to note that mappingproxy
is not JSON serializable, check out the issue了解原因。
这个类型的历史也很有趣:
- Python 2.7:
type(A.__dict__)
returns<type 'dict'>
astype(dict())
,并且可以分配新的通过__dict__
的属性,例如A.__dict__['foo'] = 'bar'
. - Python 3.0 - 3.2:
type(A.__dict__)
returns<class 'dict_proxy'>
,区别介绍。尝试分配一个新属性会得到TypeError
。有一个 attempt 添加dictproxy
作为 public 内置类型。 - Python 3.3: 添加上述
<class 'mappingproxy'>
类型。