如何使__getattr__可以选择类 [英] how to make classes with __getattr__ pickable

查看:113
本文介绍了如何使__getattr__可以选择类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何修改下面的类以使其可拾取?

How can I modify the classes below to make them pickeable?

这个问题:如何制作一个__getattr__是否可以正确拾取?与之类似,但是在使用 getattr 时引用了错误的异常.

This question: How to make a class which has __getattr__ properly pickable? is similar but refer to wrong exception in the use of getattr.

这另一个问题似乎提供了有意义的见解为什么pickle.dumps调用__getattr __?,但是它没有提供示例,老实说,我无法理解我要实现的目标.

This other question seems to provide meaningful insight Why does pickle.dumps call __getattr__?, however it fails to provide an example, and I honestly cannot understand what I am suppose to implement.

import pickle
class Foo(object):
    def __init__(self, dct):
        for key in dct:
            setattr(self, key, dct[key])


class Bar(object):
    def __init__(self, dct):
        for key in dct:
            setattr(self, key, dct[key])

    def __getattr__(self, attr):
        """If attr is not in channel, look in timing_data
        """
        return getattr(self.foo, attr)

if __name__=='__main__':
    dct={'a':1,'b':2,'c':3}
    foo=Foo(dct)
    dct2={'d':1,'e':2,'f':3,'foo':foo}
    bar=Bar(dct2)
    pickle.dump(bar,open('test.pkl','w'))
    bar=pickle.load(open('test.pkl','r'))

结果:

     14         """If attr is not in channel, look in timing_data
     15         """
---> 16         return getattr(self.foo, attr)
     17
     18 if __name__=='__main__':

RuntimeError: maximum recursion depth exceeded while calling a Python object

推荐答案

此处的问题是您的__getattr__方法实现不佳.假定self.foo存在.如果self.foo不存在,尝试访问它最终会调用__getattr__-这将导致无限递归:

The problem here is that your __getattr__ method is poorly implemented. It assumes that self.foo exists. If self.foo doesn't exist, trying to access it ends up calling __getattr__ - which results in infinite recursion:

>>> bar = Bar({})  # no `foo` attribute
>>> bar.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "untitled.py", line 19, in __getattr__
    return getattr(self.foo, attr)
  File "untitled.py", line 19, in __getattr__
    return getattr(self.foo, attr)
  File "untitled.py", line 19, in __getattr__
    return getattr(self.foo, attr)
  [Previous line repeated 329 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

要解决此问题,如果不存在foo属性,则必须抛出AttributeError:

To fix this, you have to throw an AttributeError if no foo attribute exists:

def __getattr__(self, attr):
    """If attr is not in channel, look in timing_data
    """
    if 'foo' not in vars(self):
        raise AttributeError
    return getattr(self.foo, attr)

(我使用了 vars 函数来获取对象的dict,因为它看起来比self.__dict__更好.)

现在一切正常:

dct={'a':1,'b':2,'c':3}
foo=Foo(dct)
dct2={'d':1,'e':2,'f':3,'foo':foo}
bar=Bar(dct2)
data = pickle.dumps(bar)
bar = pickle.loads(data)
print(vars(bar))
# output:
# {'d': 1, 'e': 2, 'f': 3, 'foo': <__main__.Foo object at 0x7f040fc7e7f0>}

这篇关于如何使__getattr__可以选择类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆