python列表不是复制

时间:2014-09-22 02:48:01

标签: python list python-3.x copy

在以下子集问题中,我正在尝试制作列表对象的副本

def findFourPlus(itemCount, seq, goal):
    goalDifference = float("inf")
    closestPartial = []
    subset_sum(itemCount, seq, goal, goalDifference, closestPartial, partial=[])
    print(closestPartial)


def subset_sum(itemCount, seq, goal, goalDifference, closestPartial, partial):
    s = sum(partial)

    # check if the partial sum is equals to target
    if(len(partial) == itemCount):
        if s == goal:
            print(partial)
    else:
        if( abs(goal - s) < goalDifference):
            goalDifference = abs(goal - s)
            print(goalDifference)
            print(partial)
            print(closestPartial)
            closestPartial = copy.deepcopy(partial)        

for i in range(len(seq)):
    n = seq[i]
    remaining = seq[i+1:]
    subset_sum(itemCount, remaining, goal, goalDifference, closestPartial, partial + [n])

在子集函数中,我正在尝试将 partial 列表的副本复制到 closestPartial 。我试过了

closestPartial = partial
closestPartial = list[:]
closestPartial = list(partial)
closestPartial = copy.copy(partial)
closestPartial = copy.deepcopy(partial)

但最终所有这些似乎都是徒劳的。为了某种原因,nearestPartial仍然是一个空列表(这是我发起的)

2 个答案:

答案 0 :(得分:1)

您正在将nearestPartial作为参数传递,因此唯一可行的是其列表的就地更新。您提供的所有示例都会将nearestPartial中的列表替换为新列表。但由于它不是您传入的列表,因此它不会更新真实列表。

尝试:

closestPartial[:] = partial

您可以通过在操作之前和之后打印列表ID来了解问题。

print id(closestPartial)
...some operation
print id(closestPartial)

如果id更改,则表示您创建了一个新列表,但未更新传入的列表。

修改

似乎我需要更好的解释......当你调用subset_sum时,它会创建一个名为closestPartial的局部变量,它引用作为参数传入的内容,在这种情况下是一个已知的列表来电者为closestPartial。您现在有两个指向同一列表的变量。如果您重新分配变量,就像在closestPartial = partial中一样,这两个变量现在指向不同的列表。您没有更新调用者的指针,只是更改了局部变量。相反,如果不重新分配,调用者也会看到您对两个变量引用的一个列表所做的更改 - 因为它的列表相同。

答案 1 :(得分:0)

我怀疑你的goalDifference遇到了同样的问题,如果你在一个函数中更改它,然后期望更改的值以某种方式返回到调用函数。

这里有一些(Python 2风格)代码来说明发生了什么:

#! /usr/bin/env python

def testA(update_func):
    seq = []
    num = 1
    for _ in range(5):
        newnum = update_func(seq, num)
        print 'testA:  ', num, seq, newnum
    print

def testB(update_func):
    seq = []
    num = 1
    for _ in range(5):
        num = update_func(seq, num)
        print 'testB:  ', num, seq
    print


def update0(seq, num):
    #This creates a new list
    seq = seq + [num]
    num = num + 1
    print 'update0:', num, seq
    return num

def update1(seq, num):
    #This updates the existing list
    seq.append(num)
    num += 1
    print 'update1:', num, seq
    return num

def update2(seq, num):
    #This updates the existing list
    seq[:] = seq + [num]
    num += 1
    print 'update2:', num, seq
    return num

def update3(seq, num):
    #This updates the existing list
    seq += [num]
    num += 1
    print 'update2:', num, seq
    return num


update_funcs = (update0, update1, update2, update3)
for f in update_funcs:
    testA(f)

print '------\n'

for f in update_funcs:
    testB(f)

Stack Overflow成员Ned Batchelder的文章Facts and myths about Python names and values有一个很好的解释,有可爱的图表。