在Python 3中,我有一個從另一個庫中獲得的列表和字典樹。我想用包含更多行爲的對象來測試樹中的字典(給簡單的字典類提供更豐富的模型)。我試着更換類這些對象與字典的一個子類,但這是不允許的:在Python中委派一個字典類
class MyClass(dict): pass
{}.__class__ = MyClass
失敗與TypeError: __class__ assignment: only for heap types
。
所以我不是嘗試編寫一個包裝或適配器或委託類:
class InstrumentedDict(object):
"""
Instrument an existing dictionary with additional
functionality, but always reference and mutate
the original dictionary.
>>> orig = {'a': 1, 'b': 2}
>>> inst = InstrumentedDict(orig)
>>> hasattr(inst, '__getitem__')
True
>>> inst.__getitem__('a')
1
>>> inst['a']
1
>>> inst['c'] = 3
>>> orig['c']
3
>>> inst.keys() == orig.keys()
True
"""
def __init__(self, orig):
self._orig = orig
def __getattribute__(self, name):
orig = super(InstrumentedDict, self).__getattribute__('_orig')
return orig.__getattribute__(name)
然而,在文檔測試失敗inst['a']
與TypeError: 'InstrumentedDict' object is not subscriptable
。但請注意,它不會調用__hasattr__
或__getitem__
。
我希望將所有行爲委託給底層字典,我不想考慮或明確委託字典的整個簽名。
無論這個類做什麼都會影響底層字典(而不是單獨創建對這些值的引用),這一點很重要。理想情況下,它不應該強制或否定底層映射的可變性,而應該反映其行爲。
是否有一個簡單而優雅的解決方案符合指定的界面,但不需要顯式鏡像簽名(如在this implementation中)?爲了澄清,我想覆蓋現有字典上的行爲而不創建新的副本,例如,如果修改了檢測副本,原始副本也會被修改。
我沒有看到'__getitem__' ....或'__setitem__' ... – kindall 2015-04-01 21:27:27
'inst .__ getitem __('a')'和'inst ['a']'是後者將始終在類中搜索實際的'__getitem__'(考慮到您正在使用新的樣式類)。 – 2015-04-01 21:33:39
你可能需要實現類似http://stackoverflow.com/questions/9942536/how-to-fake-proxy-a-class-in-python如果你想要一個真正的代理... – 2015-04-01 21:34:12