我有一个相当大的项目,包括一个 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/