【问题标题】:Deepcopy does not result in unique objectsDeepcopy 不会产生唯一的对象
【发布时间】:2023-03-23 03:57:01
【问题描述】:

我有一个程序可以生成一些简单的字典对象列表,例如

class loginfo:
    info = {
        'global_time': -1,
        'exptime': 0,
        'type': ""
        # omitted other entries for brevity
        }
    def assign(self, d):
        if d is not None:
            self.info.update((key, d[key]) for key in d if key in self.info)
    def __str__(self):
        s = str(self.info['global_time'])
        for key in self.info:
            if key == 'global_time':
                continue
            s += ",\t"
            s += str(self.info[key])
        s += "\n"
        return(s)

我从一个有点奇怪的日志文件中读取行,在一个单独的例程 parse_linetype 中解析它们,该例程返回一个 loginfo 对象。在将结果写入更好的日志文件之前,我想创建这些对象的列表以供进一步处理:

from copy import deepcopy
output_log = list()
version = -1
global_time = 0
with open(path+in_filename, 'r', errors="ignore") as f:
    for i, line in enumerate(f):
        log_info = parse_linetype(line, version, global_time)
        output_log.append(deepcopy(log_info))
        # debug print:
        print(i,": ",line, len(output_log), "\n", str(output_log[len(output_log)-1]), str(output_log[0]))

然而,这段代码——对我来说出乎意料——返回了一个相同对象的列表,即使我在附加列表时已经对对象进行了深度复制。对象从 parse 函数正确返回 - 实际上作为一个额外的好处 - 解析的日志行中不可用的信息是从前一个日志行中继承的。但是这种结转不应该影响存储在 output_log 中的对象中存储的内容。

在创建真实的深层副本时我哪里出了问题,我在哪里继续使用参考以及为什么?

调试打印的典型输出当前看起来像这样(并看到解析的行和返回的对象确实不同 - 但 output_log 中的所有对象总是相同的。这里的 'AIN' 和 'OTHER' 是更改的部分记录 - 但第一条记录(因此第二行用于比较)当然永远不会改变):

6288 :  [10:03:04.546] AIN, 57668, 970, Device handling terminates
 6289 
-1,  56797, AIN

 -1,     56797, AIN


6289 :  57670: Terminating experiment loop
 6290
 -1,     56797, OTHER

 -1,     56797, OTHER

【问题讨论】:

    标签: python python-3.x deep-copy python-3.8


    【解决方案1】:

    Deepcopy 不复制类,只复制实例。它假设任何共享的类资源设计都是共享的,并且您将info 字典设置为类属性。

    copy module documentation 对此是这么说的:

    此模块不会复制模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口、数组等类型或任何类似类型。 它通过原样返回原始对象来“复制”函数和类(浅层和深层);这与pickle 模块处理这些的方式兼容。

    (我的粗体强调)。

    将字典移至 instance 属性:

    class loginfo:
        def __init__(self):
            self.info = {
                'global_time': -1,
                'exptime': 0,
                'type': ""
                # omitted other entries for brevity
            }
    
        # ...
        # assign and __str__ unchanged.
    

    【讨论】:

    • 哦,我明白了!我没有意识到这种差异——虽然很大!感谢您的信息
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 2012-08-31
    相关资源
    最近更新 更多