我有一个类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/

10-14 10:21