在 python 中保持列表分开并避免浅拷贝

keeping lists separate and avoiding shallow copy in python

这是我的伪代码:

class foo(bar):
    def __init__(self, aList):
        bar.__init__(self, aList)
        self.initialList = aList
    def clock(self):
        modify(self.workingList)
        if(something):
            self.workingList = self.initialList
        assert self.initialList == range(10)

class bar(object):
    def __init__(self, aList):
        self.workingList = aList

程序的正常运行是这样的:

a = range(10)
b = foo(a)
for i in xrange(10000):
    b.clock()

这没有用,因为当我这样做时

self.workingList = self.initialList

self.workingList 指向同一个对象而不是复制它。那么当我做

modify(self.workingList)

它还修改了 self.initialList,这意味着保持不变。

我的解决方案是用

self.workingList = self.initialList

self.workingList = [i for i in self.initialList]

我什至替换了

self.initialList = aList

与:

self.initialList = [j for j in aList]

虽然我认为这在原则上应该可行,但在实践中并没有解决问题。我通过 assert 语句验证这一点。好像我误解了一些 pythonic 语义。有人可以解释一下吗?

谢谢!

编辑: 请注意,我了解 deepcopy 和 shallowcopy 之间的区别。那不是我的问题。当我在 class instantiation/inheritance 中使用它时,我觉得有些事情搞砸了。我正在离线工作以生成我可以在此处提供的 MCV 代码段。请继续关注该更新。

更新:

我在 MCVE 中找到了 C,这里是错误:

class bar(object):
    def __init__(self, aList):
        self.workingList = aList

class foo(bar):
    def __init__(self, aList):
        bar.__init__(self, aList)
        self.initialList = list(aList)
    def clock(self):
        self.workingList[2] = max(self.workingList[3], 2)
        #print self.workingList
        if(1):
            self.workingList = list(self.initialList)
        try:
                assert self.initialList == range(10)
        except:
                print self.initialList
                print self.workingList
                assert self.initialList == range(10)


a = range(10)
for i in xrange(10):
        b = foo(a)
        for j in xrange(100000):
                b.clock()

所以经过大量的调试我找到了这个错误的原因。一种可能的修复方法如下:

class bar(object):
    def __init__(self, aList):
        self.workingList = list(aList) #aList

原因是 python 按值传递对象引用。这里有一个 link 很好地解释了它。

它与我的代码有关的方式是每次我在 foo.clock() 中更改 self.workingList:

modify(self.workingList)

它实际上修改了 aList 指向的对象(在构造函数之外!!),所以当我创建 foo(aList) 的新实例时,我将一个新的错误版本的 aList 传递给它。这太棘手了!

最棘手的事情是重新分配 self.workingList 不会产生这个错误(尽管它会在传递引用中产生),但是修改 self.workingList 会,因为 python 传递对象- 按值引用(所有这些都在 link 中有详细说明)