从__init__函数中的pickle初始化对象

时间:2017-05-14 14:59:32

标签: python constructor initialization pickle

我有一个类,我希望根据参数以多种方式实例化对象。当我将文件路径传递给函数__init__时,它应该从保存为pickle文件的对象中恢复所有参数。有没有聪明的方法可以做到这一点,比如self=load(...)

3 个答案:

答案 0 :(得分:4)

Persistent中执行self=load(...)只会屏蔽__init__中的本地self变量,但不会更改实例。

您可以在类的__new__方法中控制新实例的创建。

__init__

您可以对unpickled对象进行快速实例检查,以确保它实际上是您的类的实例,否则您可能会遇到不良行为,例如您的类的import pickle class Pretty(object): def __new__(cls, filepath=None, *args, **kwargs): if filepath: with open(filepath) as f: inst = pickle.load(f) if not isinstance(inst, cls): raise TypeError('Unpickled object is not of type {}'.format(cls)) else: inst = super(Pretty, cls).__new__(cls, *args, **kwargs) return inst 方法未被调用。

答案 1 :(得分:2)

如另一个答案所述,self = load(...)仅替换局部变量self。同样的答案建议使用类的__new__方法,但这在python中不是一个好习惯,因为重写此方法只能用于不可变类型。

相反,你应该使用factory,在这种情况下可以是一个简单的函数:

def foo_factory(filename=None, *args, **kwargs):
    if filename:
        foo_factory.foo = pickle.load(filename)
    else:
        foo_factory.foo = Foo(*args, **kwargs)
    return foo_factory.foo

我们认为类Foo是感兴趣的类。

(有关更多详情和参考,请参阅Why is __init__() always called after __new__()?

答案 2 :(得分:1)

这可能不是“聪明的方法”,但是如果您喜欢第三个选项(除了新增和出厂设置):

class myclass:

  def __init__(self, filename):

    with open(filename, 'rb') as f:
      myinstance = pickle.load(f)

    for k in myinstance.__dict__.keys():
      setattr(self, k, getattr(myinstance, k))

这会循环访问已加载实例的所有属性(myinstance),并在已初始化的实例(自身)中设置相应的属性。