Deepcopy 不会产生唯一的对象

Deepcopy does not result in unique objects

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

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 中解析它们,其中 returns 一个单独的登录信息对象。在将结果写入更好的日志文件之前,我想创建这些对象的列表以供进一步处理:

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]))

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

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

copy module documentation 是这样说的:

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

(大胆强调我的)。

将字典移至 实例 属性:

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

    # ...
    # assign and __str__ unchanged.