如何复制复杂对象以便我可以添加新成员?当我尝试使用深度复制时,它会失败并显示“TypeError: cannot serialize
...”
最初的问题是我想将一些成员变量添加到现有对象但不能,因为这样做会导致“AttributeError: Object is fixed
”
因此,我们的想法是在添加了成员的新类中创建原始对象的完整副本。
orig_obj = SomeSqlObject.get_root() # contents unclear, complex
class orig_expanded():
def __init__(self, replicable_object):
self.__dict__ = copy.deepcopy(replicable_object.__dict__)
self.added_member1 = None
self.added_list = []
expanded_thing = orig_expanded(orig_obj)
但我明白了:
TypeError: cannot serialize '_io.TextIOWrapper' object
回答评论,“什么是SomeSqlObject?” 也许我的名字是错的......实际名称对公司来说是模糊的。它是一个方法,它返回一个表示树的基础的对象(某种树)定义了树
class SomeSqlObject(ParentRegisterSet):
"""
Implements the functionality of the Device "root" Register Set.
"""
def __init__(self, db, v1, dg, ui):
self.__db__ = db
self.__dg__ = dg
self.__ui__ = ui
SomeSqlObject.__init__(self, v1, None)
# note: this class is now locked
答案 0 :(得分:3)
copy.deepcopy
对不提供直接支持的类(通过定义__deepcopy__
)的行为是pickle
然后unpickle
对象以确保新实例是创建。 io.TextIOWrapper
(它是将二进制文件类对象转换为类文本对象的包装器)无法序列化(因为它假定它可能具有外部/运行时状态,例如具有特定文件描述符的文件描述符)文件中的位置,以后反序列化时可能无法使用。)
出现错误的原因是您复制的对象包含io.TextIOWrapper
,并且序列化失败。
如果共享状态没问题,您可以将自己限制为浅层副本,或者使用基于组合的包装器(基于__getattr__
)半无缝地通过包装器对象访问底层对象(除了那些)讨厌的special methods),或者您可能会尝试单独深度查看字典中的值,只是忽略您无法复制的值,例如:
for attr, value in vars(replicable_object).items():
try:
setattr(self, attr, copy.deepcopy(value))
except Exception:
pass
# Alternatively, copy reference when copy impossible:
#setattr(self, attr, value)
并希望你不能复制的东西不是太重要。
答案 1 :(得分:1)
我的猜测是你真正想要的是一个代理类,谷歌的一个例子: http://python-3-patterns-idioms-test.readthedocs.org/en/latest/Fronting.html
您将从要包装的对象初始化您的代理类;代理类知道的属性在本地处理;代理类不知道的属性将传递给包装对象。
(通常情况下,如果您自己创建这些对象,则会进行子类化...听起来这不是一个选项......)
答案 2 :(得分:0)
TypeError: cannot serialize '_io.TextIOWrapper' object
这个异常意味着在某个地方,你的对象以某种方式链接到文件对象,套接字或类似的东西。
TextIOWrapper
是包装文件描述符的类,允许您读/写unicode字符串。
而且,正如您所看到的,TextIOWrapper
无法复制。
答案 3 :(得分:0)
好的找到答案。
尝试执行setattr()
时看到的原始错误是AttributeError: Object is fixed.
这是原始SomeSqlObject中的代码中的错误,该代码正在查找位{{1}的自定义__setatter__()
并阻止向对象添加成员。一旦我取消了这个锁定,我就可以轻松添加成员了。
最初的问题是,我有一些_attr_lock
,id0
,id1
,id3
形式的班级成员(称为id' s)等等。它们中的每一个也是一个复杂的对象。但是,从代码用户的角度来看,更好的方法是使用列表类型成员id2
来访问它们。所以,我需要添加一个列表类型成员id[#]
,并确保每个连续元素指向id[]
,id0
所指向的相同对象,即。 id1
,id[0]
等
因此,我的最终代码是采用复杂对象并添加列表类型成员。
id[1]