gpt4 book ai didi

python - 类 X 的 __new__ 方法中的 X 类型的 Unpickling 对象在返回 unpickled 对象时调用 __init__,为什么?

转载 作者:太空宇宙 更新时间:2023-11-04 00:52:47 25 4
gpt4 key购买 nike

我有一个对象,它会在第一次使用后被缓存。我将使用 cPickle 模块执行此操作。如果模块已经被缓存,当我下次尝试实例化对象时(在另一个进程中)我想使用缓存的对象。以下是我的基本结构:

import cPickle
class Test(object):
def __new__(cls, name):
if name == 'john':
print "using cached object"
with open("cp.p", "rb") as f:
obj = cPickle.load(f)
print "object unpickled"
return obj
else:
print "using new object"
return super(Test, cls).__new__(cls, name)
def __init__(self, name):
print "calling __init__"
self.name = name
with open("cp.p", "wb") as f:
cPickle.dump(self, f)

问题是,当我在 __new__ 方法中取消缓存对象时,它会调用 __init__ 并重新初始化所有内容。有趣的是,似乎 __init__ 不是在 unpickling 之后调用,而是在返回 unpickled 对象时调用。我添加了一个打印语句来显示这一点(“未 pickle 的对象”)。

通过向 __init__ 添加以下检查,我有一个 hacky 解决方法:

intiailzed = False
...
...
def __init__(self, name):
if not self.intialized:
self.initialized = True
# Rest of the __init__ here

还有一个class属性叫initialized,但这显然不太理想。

任何关于如何抑制 __init__ 方法(或者为什么调用它)的见解都将不胜感激。

编辑:根据这里的反馈,我提出了新的解决方案:

class Test(object):
def __new__(cls, name=None):
print "calling __new__"
if name == 'john':
print "using cached object"
with open("cp.p", "rb") as f:
obj = cPickle.load(f)
print "object unpickled"
return obj
else:
print "using new object"
obj = super(Test, cls).__new__(cls, name)
obj.initialize(name)
return obj

def __init__(self, name):
pass

def initialize(self, name):
print "calling __init__"
self.name = name
with open("cp.p", "wb") as f:
cPickle.dump(self, f)

最佳答案

obj = Test(name) 是这样工作的:

obj = Test.__new__(Test, name)
if isinstance(obj, Test):
obj.__init__(name)

由于从 Test.__new__(Test, name) 返回的 unpickled 对象是 Test 的一个实例,它的 __init__ 方法被调用。对象是来自 super(Test, cls).__new__ 还是 unpickling 并不重要。

为避免此类问题,覆盖 __new__ 的类通常应从 __new__ 返回完全初始化的对象,而不是定义 __init__。它们的子类也应该遵循这个规则。

关于python - 类 X 的 __new__ 方法中的 X 类型的 Unpickling 对象在返回 unpickled 对象时调用 __init__,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36458221/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com