注:本人在CSDN上也發(fā)表了這篇文章(https://blog.csdn.net/tonytong787/article/details/105116330/)载萌,此文屬原創(chuàng),而非轉(zhuǎn)載
眾所周知且警,python大部分對(duì)象的屬性都是由dict特殊屬性完成的,而且這個(gè)dict不僅對(duì)象可改變,而且這個(gè)屬性本身就可改變个扰。
class _C(object):pass
obj = _C()
obj.sth = 10
print obj.__dict__ #{'sth':10}
obj.__dict__['sth'] = 100
print obj.sth #100`
同樣的,在Python中葱色,類(lèi)也是對(duì)象递宅。
print _C.__dict__ #dictproxy({})
等等,dictproxy是什么玩意苍狰?沒(méi)聽(tīng)說(shuō)過(guò)呀办龄!
甭管了,反正看上去跟dict差不多淋昭,就把它當(dāng)dict來(lái)處理吧俐填!
_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})
那這是怎么回事英融,怎么還改變了呢!
這得舉一個(gè)生活中的例子歇式。
假如你有一個(gè)房間驶悟,你自己和你的家人可以隨意查看這個(gè)房間并挪動(dòng)里面的東西,這個(gè)房間就相當(dāng)于一個(gè)dict
材失。
突然有一天痕鳍,一個(gè)消防員說(shuō)這個(gè)房間有問(wèn)題,電路自燃的可能性很大豺憔,并且申請(qǐng)時(shí)時(shí)刻刻檢查這個(gè)房間额获。但你總不能讓他隨便進(jìn)出這個(gè)房間啊,你于是在房間的安全的地方按了一個(gè)監(jiān)控恭应,讓他遠(yuǎn)程看抄邀。這個(gè)監(jiān)控就相當(dāng)于一個(gè)dictproxy
。
proxy在英文中是代理的意思昼榛,直譯過(guò)來(lái)就是“dict的代理”境肾。通過(guò)這個(gè)代理剔难,你可以查看類(lèi)中的屬性,但不能修改它奥喻,要修改只能用_C.x = 20
這樣的傳統(tǒng)修改方式偶宫。
但是,dictproxy這個(gè)類(lèi)是不能直接實(shí)例化的环鲤,要實(shí)例化必須利用Python API纯趋。
import ctypes
PyDictProxy_New = ctypes.pythonapi.PyDictProxy_New #實(shí)例化API函數(shù)
PyDictProxy_New.argtypes = (ctypes.py_object,) #設(shè)置參數(shù)類(lèi)型
PyDictProxy_New.restype = ctypes.py_object #設(shè)置返回值類(lèi)型
mydict = {}
mydictproxy = PyDictProxy_New(mydict)
這樣就建立了dict對(duì)象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})