自定义__getattr__返回其他对象属性

时间:2018-06-28 08:13:55

标签: python

import random

class Foo(object):
    def __init__(self):
        self._name = ''.join([chr(65 + random.randrange(0, 26)) for _ in range(3)])
        self._data = None

    def __getattr__(self, item):
        dashitem = '_' + item
        # if dhasattr(self, dashitem):
        # is a bad idea because hasattr calls getattr
        # is in self.__dict__.keys() also a bad idea?
        if dashitem in self.__dict__.keys():
            return self.__dict__[dashitem]

obj = Foo()
obj._data = [random.randrange(10, 100) for _ in range(random.randrange(1, 11))]

到目前为止,太好了。我可以叫obj.name and get back obj._name`

In [2]: obj.name
Out[2]: 'QZB'

In [3]: obj.data
Out[3]: [54]

然后我尝试腌制对象:

import pickle
pickle.dumps(obj)

虽然不行。

  File "<ipython-input-7-a7748eba906b>", line 2, in <module>
    pickle.dumps(obj)
  File "/usr/local/Cellar/python/2.7.14_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1380, in dumps
    Pickler(file, protocol).dump(obj)
  File "/usr/local/Cellar/python/2.7.14_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/local/Cellar/python/2.7.14_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/Users/vishal/virtenvs/fm/bin/../lib/python2.7/copy_reg.py", line 84, in _reduce_ex
    dict = getstate()

如何使用上面的__getattr__做我想做的事情(如果未找到_<attr>而不破坏其他正常行为,请返回<attr>

1 个答案:

答案 0 :(得分:1)

最简单的方法是简单地防止无限递归,并让默认逻辑处理其余部分。重要的是,不要隐式返回None(在省略的else情况下进行此操作)并打破默认行为(即在找不到属性时引发AttributeError):

# ...
def __getattr__(self, item):
    # all double-underscore attrs should be found before calling the fallback
    if item.startswith('__'):  
        raise AttributeError
    return getattr(self, '_'+item)

另请参阅this questiondocs