pickle如何无视构造函数创建实例?

我的最终目标是拥有一个具有常规构造函数的类,以及可用于创建类的部分实例化版本的第二个构造函数。

class Foo(object):
   def __init__(self, foo, bar):
      self.foo = foo
      self.bar = bar
   def create_partial(self, **kwargs):
      self.foo = kwargs.get('foo', None)
      self.bar = kwargs.get('bar', None)

我注意到泡菜以某种方式实现了这一点。您可以编写__getstate____setstate__功能,只有处理参数之一,它忽略你还没有定义其中的一个事实。例如

class Foo(object):
  def__init__(self, foo, bar):
    self.foo = foo
    self.bar = bar
  def __getstate__(self):
    return {'foo': self.foo}
  def __setstate__(self, d):
    self.foo = d['foo']

然后我可以pickle和unpickle一个实例来获得一个半实例化的对象

myfoo = pickle.loads(pickle.dumps(Foo(1,2)))
print(myfoo.foo) # 1
print(myfoo.bar) # throws AttributeError
type(myfoo) # __main__.Foo

所以,我的问题是,它如何设法获得该类的一个空白实例,对其进行一半实例化,并让它仍将其类型报告为 Foo,此外,我如何在不经过 pickle 的情况下执行相同操作?

PS我知道这是一个疯狂的事情去做,但我想知道如何

回答

当您跑步时Foo(),我们认为这是在调用Foo.__init__()。但实际上,在此之前还有一个额外的步骤,即创建对象。foo = Foo(a, b, c)大致相当于

foo = Foo.__new__(Foo, a, b, c)
foo.__init__(a, b, c)

__new__是一种很少使用的魔法方法,它实际构造了对象。您几乎不需要覆盖它(覆盖它的最常见用例是在子类化像 那样的内置类型时float),并且大多数类继承默认的object.__new__. 我们可以直接调用后一个函数。

# Assuming that Foo doesn't override __new__
myfoo = Foo.__new__(Foo)
# Or, to be extra safe
myfoo = object.__new__(Foo)

请注意,__new__将预期类型作为第一个参数,因此即使我们调用object.__new__,我们仍然会得到 a,Foo因为我们Foo作为参数传递。在此过程中,没有施工人员受到伤害。


以上是pickle如何无视构造函数创建实例?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>