2

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

解决办法是什么?也许标准库中有这样的代理?

4

2 回答 2

6

您正在尝试在您的实例上设置一个新属性:Proxy

class LabelMapperProxy(object):
    def __init__(self, mapper): self.mapper = mapper

这会触发 a __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
于 2013-04-17T13:24:51.277 回答
1

这是陷阱:

class LabelMapperProxy(object):
   def __init__(self, mapper):
       # This will not assign this object's attribute 
       # since __setattr__ is overriden.
       # Instead, it will do self.mapper['mapper'] = mapper
       self.mapper=mapper

   def __getattr__(self, key): 
       # And this won't find `self.mapper` and resort to __getattr__
       # (which is itself)
       return self.mapper[key]  

   def __setattr__(self, key, val): 
       self.mapper[key]=val

   def __delattr__(self, key): 
       del self.mapper[key]
于 2013-04-17T13:25:13.213 回答