注:本人在CSDN上也发表了这篇文章(https://blog.csdn.net/tonytong787/article/details/105116330/),此文属原创,而非转载
众所周知,python大部分对象的属性都是由dict特殊属性完成的,而且这个dict不仅对象可改变,而且这个属性本身就可改变。
class _C(object):pass
obj = _C()
obj.sth = 10
print obj.__dict__ #{'sth':10}
obj.__dict__['sth'] = 100
print obj.sth #100`
同样的,在Python中,类也是对象。
print _C.__dict__ #dictproxy({})
等等,dictproxy是什么玩意?没听说过呀!
甭管了,反正看上去跟dict差不多,就把它当dict来处理吧!
_C.__dict__['x'] = 20
'''
Traceback (most recent call last):
File "D:\test.py", line 8, in <module>
_C.__dict__['x'] = 20
TypeError: 'dictproxy' object does not support item assignment
'''
什么情况!dictproxy居然不可改变!
_C.x = 20
print _C.__dict__ #dictproxy({'x':20})
那这是怎么回事,怎么还改变了呢!
这得举一个生活中的例子。
假如你有一个房间,你自己和你的家人可以随意查看这个房间并挪动里面的东西,这个房间就相当于一个dict
。
突然有一天,一个消防员说这个房间有问题,电路自燃的可能性很大,并且申请时时刻刻检查这个房间。但你总不能让他随便进出这个房间啊,你于是在房间的安全的地方按了一个监控,让他远程看。这个监控就相当于一个dictproxy
。
proxy在英文中是代理的意思,直译过来就是“dict的代理”。通过这个代理,你可以查看类中的属性,但不能修改它,要修改只能用_C.x = 20
这样的传统修改方式。
但是,dictproxy这个类是不能直接实例化的,要实例化必须利用Python API。
import ctypes
PyDictProxy_New = ctypes.pythonapi.PyDictProxy_New #实例化API函数
PyDictProxy_New.argtypes = (ctypes.py_object,) #设置参数类型
PyDictProxy_New.restype = ctypes.py_object #设置返回值类型
mydict = {}
mydictproxy = PyDictProxy_New(mydict)
这样就建立了dict对象mydict的代理mydictproxy。
print mydictproxy #dictproxy({})
print hasattr(mydictproxy, '__setitem__') #False
mydict.update(one=1, two=2, three=3)
print mydictproxy #dictproxy({'two': 2, 'three': 3, 'one': 1})