问题:我怎样才能拦截__getitem__
调用对象属性?
解释:
所以,场景如下。我有一个对象将类似字典的对象存储为属性。每次__getitem__
该属性的方法被调用,我想拦截该调用并根据键对获取的项目进行一些特殊处理。我想要的看起来像这样:
class Test:
def __init__(self):
self._d = {'a': 1, 'b': 2}
@property
def d(self, key):
val = self._d[key]
if key == 'a':
val += 2
return val
t = Test()
assert(t.d['a'] == 3) # Should not throw AssertionError
问题是 @property 方法实际上无法访问__getitem__
调用,所以我根本无法检查它来执行我的特殊后处理步骤。
重要提示:我不能只是子类化 MutableMapping,重写__getitem__
我的子类的方法来执行此特殊处理,并将子类的实例存储在self._d
。在我的实际代码中self._d
已经是 MutableMapping 的子类,并且该子类的其他客户端需要访问未修改的数据。
感谢您的任何帮助!
一种解决方案是Mapping
代理底层映射。这d
属性将包裹底层self._d
在代理包装器中映射并返回它,并且使用该代理将表现出必要的行为。例子:
from collections.abc import Mapping
class DProxy(Mapping):
__slots__ = ('proxymap',)
def __init__(self, proxymap):
self.proxymap = proxymap
def __getitem__(self, key):
val = self.proxymap[key]
if key == 'a':
val += 2
return val
def __iter__(self):
return iter(self.proxymap)
def __len__(self):
return len(self.proxymap)
一旦你做到了,你原来的课程可以是:
class Test:
def __init__(self):
self._d = {'a': 1, 'b': 2}
@property
def d(self):
return DProxy(self._d)
然后用户将访问实例Test
with test.d[somekey]
; test.d
将返回代理,然后代理将修改结果__getitem__
根据需要somekey
。他们甚至可以存储参考资料locald = test.d
然后使用locald
同时保留必要的代理行为。你可以把它变成一个MutableMapping
如果需要的话,但是一个简单的Mapping
当目标是读取值而不是通过代理修改它们时,基于代理可以避免复杂性。
是的,这创造了一个新的DProxy
每次访问时的实例d
;如果您愿意,您可以缓存它,但考虑到它的简单性DProxy
班级的__init__
也就是说,只有通过合格的访问,成本才有意义d
属性在最热门的代码路径上频繁执行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)