读取二进制文件到结构体列表,但深度复制会覆盖第一个结构体。

3
我正在将一个二进制文件读入到一个类实例的列表中。我有一个循环,从文件中读取数据到一个实例中。当实例被填充后,我将实例附加到一个列表中并重新开始读取。
这个方法很好用,但是其中一个实例元素是一个Rect(即矩形),它是一个用户定义的类型。即使使用deepcopy,属性也会被覆盖。
有一些解决方法,比如不把Rect作为用户定义的类型。然而,我可以看到这是一个我经常会遇到的情况,并希望有一个简单明了的解决方案,允许我在循环中读取嵌套类型。
以下是一些代码:
class Rect:
    def __init__(self):
        self.L = 0

class groundtruthfile:
    def __init__(self):
        self.rect = Rect
        self.ht = int
        self.wt = int
        self.text = ''
        ...

data = []
g = groundtruthfile()
f = open("datafile.dtf", "rb")
length = unpack('i', f.read(4))
for i in range(1,length[0]+1): #length is a tuple
    g.rect.L = unpack('i',f.read(4))[0]
    ...
    data.append(copy.deepcopy(g))

这个结果正是我想要的,但所有的 data(i).rect.L 都是最后读取的数据值。

2
你正在显式地修改同一个Rect实例(实际上是,在groundtruthfile.__init__中没有实例化一个实例,该实例应该被命名为GroundTruthFile),你为什么希望有不同的行为呢?! - jonrsharpe
1
@DSM 是的,刚刚注意到了 - 在这里称Python为不直观有些过分了! - jonrsharpe
1个回答

4
你在这里面有两个问题:
  1. The rect attribute of a groundtruthfile instance (I'll just put this here...) is the Rect class itself, not an instance of that class - you should be doing:

    self.rect = Rect()  # note parentheses
    

    to create an instance, instead (similarly e.g. self.ht = int sets that attribute to the integer class, not an instance); and

  2. The line:

    g.rect.L = unpack('i',f.read(4))[0]
    

    explicitly modifies the attribute of the same groundtruthfile instance you've been using all along. You should move the line:

    g = groundtruthfile()
    

    inside the loop, so that you create a separate instance each time, rather than trying to create copies.

这只是一个最小的修复 - 实际上提供各种__init__方法的参数是有意义的,例如,这样您可以以更直观的方式创建实例。


另外,如果您在循环中实际上没有使用i

for _ in range(length[0]):

比起这样写:

更整洁:

for i in range(1,length[0]+1):

谢谢回复。 - j t
我足够让程序工作,目前来说已经足够了。但我仍然不理解deepcopy的功能:我原以为它会显式地创建一个新实例,有点像Excel中的“复制值”。我一直试图保持相同的内存引用,每次只更改该内存位置的值(我认为这就是发生的事情)。我还以为append(deepcopy)语句会使用每个append(deepcopy())语句创建一个新变量data[i](即使i没有被明确使用),该变量仅填充值。那么,deepcopy到底是做什么的? - j t
@jt deepcopy仅适用于实例属性,而不适用于类属性 - 例如,请参见https://dev59.com/NWMl5IYBdhLWcg3we3Do - jonrsharpe
好的,谢谢。我会试着去操作它,看看能否更好地掌握它。 - j t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接