复制复杂对象时为什么深度复制失败

时间:2015-09-15 18:23:20

标签: python object python-3.x

如何复制复杂对象以便我可以添加新成员?当我尝试使用深度复制时,它会失败并显示“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

4 个答案:

答案 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_lockid0id1id3形式的班级成员(称为id' s)等等。它们中的每一个也是一个复杂的对象。但是,从代码用户的角度来看,更好的方法是使用列表类型成员id2来访问它们。所以,我需要添加一个列表类型成员id[#],并确保每个连续元素指向id[]id0所指向的相同对象,即。 id1id[0]

因此,我的最终代码是采用复杂对象并添加列表类型成员。

id[1]