python - 在加载旧对象时使用 python 的属性

标签 python properties pickle

我有一个相当大的项目,包括一个 Foo 类,最近需要使用 @property 装饰器进行更新,以创建自定义的 getter 和 setter 方法。

我还在我的硬盘驱动器上存储了几个 Foo 实例,在某些时候我可能需要重新加载它们。我的问题是,我无法访问这些旧对象上用属性装饰的属性。

考虑以下示例:

import pickle

# define Class and create instance
class Foo:
    def __init__(self):
        self.val = 1
foo = Foo()

# dump foo into file
with open("foo.pickle", 'wb') as handle:
    pickle.dump(foo, handle, pickle.HIGHEST_PROTOCOL)

# overwrite and add @property in the class definition
class Foo:
    def __init__(self):
        self._val = "new_foo"

    @property
    def val(self):
        return self._val

    @val.setter
    def val(self, val):
        self._val = val

foo_new = Foo()
print(foo_new.val)

# reload foo
with open("foo.pickle", "rb") as handle:
    foo_old = pickle.load(handle)

# try to access attributes
print(foo_old.val)

最后一行加注:

NameError: name '_val' is not defined

我有哪些选择仍然可以访问我的存档实例的属性?

编辑:在第二个 Foo 定义的构造函数中将 self.val 更改为 self._val

最佳答案

pickle documentation说:

When a class instance is unpickled, its __init__() method is usually not invoked.

这就是未定义 _val 属性的原因您可以通过在替换 Foo 类中定义一个 __new__ 方法并设置来解决这个问题那里的实例属性:

import pickle

# define Class and create instance
class Foo:
    def __init__(self):
        self.val = 1
foo = Foo()

# dump foo into file
with open("foo.pickle", 'wb') as handle:
    pickle.dump(foo, handle, pickle.HIGHEST_PROTOCOL)

# overwrite and add @property in the class definition
class Foo:
    def __new__(cls, val=None):
        inst = super().__new__(cls)
        inst._val = "new_foo"  if val is None else val
        return inst

    @property
    def val(self):
        return self._val

    @val.setter
    def val(self, val):
        self._val = val

foo_new = Foo()
print(foo_new.val)  # -> new_foo

# reload foo
with open("foo.pickle", "rb") as handle:
    foo_old = pickle.load(handle)

print(foo_old.val)  # -> new_foo

关于python - 在加载旧对象时使用 python 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49197079/

相关文章:

python - 禁止 (403) CSRF 验证失败。请求中止。即使使用 {% csrf_token %}

windows - Pickled Matplotlib 3D 缺乏交互功能

Python - Blender Game Engine : _pickle. PicklingError: Can't pickle <class '__main__."a class "'>: attribute lookup "a class"on __main__ failed

python - 在装饰器内部使用多处理会产生错误 : can't pickle function. ..找不到

python - 如果 x 在多个列表中的任何一个中,我如何返回 True?

python - 使用 numpy 的 k 最近邻分类器

python - 如何创建 Conda 包/应用程序的入口点?

java - 有没有办法在 Apache PropertiesConfiguration 中使用占位符

java - 为什么在类路径中(在 WEB-INF/lib 下)我无法使用 getResourceAsStream 读取属性文件

properties - Google 关闭编译器 : Declaring properties in externs