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作为参数传递。在此过程中,没有施工人员受到伤害。