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>
?
答案 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 question和docs。