eud*_*xos 2 python proxy-classes
我有一个类LabelMapper(一个boost::python类),它实现了字典协议.我想有一个代理类,它将使用属性来访问该dicionary.我已经看过许多重写的帖子__setitem__,__getitem__但我似乎无法做到正确.
天真的方法(下面)导致无限递归,因为self.mapper调用LabelMapperProxy.__getattr__,反过来需要self.mapper等等.
class LabelMapper(object):
def __init__(self): self.map={}
def __getitem__(self,key): return self.map[key]
def __setitem__(self,key,val): self.map[key]=val
def __delitem__(self,key): del self.map[key]
class LabelMapperProxy(object):
def __init__(self,mapper): self.mapper=mapper
def __getattr__(self,key): return self.mapper[key]
def __setattr__(self,key,val): self.mapper[key]=val
def __delattr__(self,key): del self.mapper[key]
lm=LabelMapper()
lm['foo']=123
# construct the proxy
lmp=LabelMapperProxy(mapper=lm)
print lmp.foo # !!! recursion
lmp.bar=456
print lmp.bar,lm['bar']
Run Code Online (Sandbox Code Playgroud)
解决办法是什么?也许在标准库中预先煮好这样的代理?
您正尝试在实例上设置新属性Proxy:
class LabelMapperProxy(object):
def __init__(self, mapper): self.mapper = mapper
Run Code Online (Sandbox Code Playgroud)
这会触发a __setattr__,它会尝试访问不存在的self.mapper属性,因此会__getattr__被查询(对所有缺少的属性都会调用).并__getattr__尝试访问self.mapper....
解决方案是mapper直接设置self.__dict__:
class LabelMapperProxy(object):
def __init__(self, mapper): self.__dict__['mapper'] = mapper
Run Code Online (Sandbox Code Playgroud)
或者,__setattr__仅为mapper属性使用原始基类:
class LabelMapperProxy(object):
def __init__(self, mapper): self.mapper = mapper
def __setattr__(self, key, val):
if key == 'mapper':
return super(LabelMapperProxy, self).__setattr__(key, val)
self.mapper[key] = val
Run Code Online (Sandbox Code Playgroud)