我有一个类LabelMapper
(一个boost::python
类),它实现字典协议。我想有一个代理类,它将使用属性来访问该目录。我看过很多关于覆盖__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']
解决办法是什么?也许在标准库中有这样的预煮代理吗?
最佳答案
您正试图在Proxy
实例上设置新属性:
class LabelMapperProxy(object):
def __init__(self, mapper): self.mapper = mapper
这触发了
__setattr__
,它试图访问不存在的self.mapper
属性,因此咨询__getattr__
(它被称为所有缺少的属性)。并且__getattr__
尝试访问self.mapper
。。。。解决方案是在
mapper
中直接设置self.__dict__
:class LabelMapperProxy(object):
def __init__(self, mapper): self.__dict__['mapper'] = mapper
或者,将原始基类
__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
关于python - 代理类,用于将其他类的项作为属性访问(__getitem__无限递归),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16061041/