微妙地访问和修改多维列表

时间:2012-08-09 01:04:05

标签: python list python-2.7

当我今晚写了一些代码时,我遇到了一个问题,即使它没有阻止我,引起了我的注意,因为我无法理解。所以这是我写的一个函数(不应该是最好的方法,但是没关系......)

def ownShuffle( origin ):
    export  = [[] for i in range( len( origin ) ) ]
    indices = range( len( origin ) )
    for n, item in enumerate( origin ):
        i = random.randrange( len( indices ) )
        export[indices[i]] = item
        indices.remove(indices[i])
    return export

现在有一个像这样的测试样本:

c = [[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]

有问题的部分。我用几乎相同的代码得到不同的结果。 如果它写这个:

for i, line in enumerate(c):
    c[i] = ownShuffle(line)

print c
>>> [[3, 2, 1],
     [6, 4, 5],
     [7, 8, 9]]

我得到了一个洗牌清单。但是使用以下代码:

for i, line in enumerate(c):
    line = ownShuffle(line)

print c
>>> [[1, 2, 3], 
     [4, 5, 6], 
     [7, 8, 9]]

我将测试样本保持不变。也许它来自我写的功能?我不知道......

所以问我的问题:有谁知道为什么?

谢谢:)

1 个答案:

答案 0 :(得分:1)

for i, line in enumerate(c):
    line = ownShuffle(line)

您不断创建临时line,但它与原始列表c的引用不同。实际上,您需要影响line内的值才能反映原始对象。

您可以通过执行以下操作来看到它改变同一line内的值:

for i, line in enumerate(c):
    line[:] = ownShuffle(line)

这是一种可视化正在发生的事情的方法:

for i, line in enumerate(c):
    id_before = id(line)
    line = ownShuffle(line)
    print id_before, "=>", id(line)
# 4973032728 => 4973032656
# 4973034312 => 4973032656
# 4973034240 => 4973032656

for i, line in enumerate(c):
    id_before = id(line)
    line[:] = ownShuffle(line)
    print id_before, "=>", id(line)
# 4973032728 => 4973032728
# 4973034312 => 4973034312
# 4973034240 => 4973034240

在第一个中你可以看到它总是一个临时对象。而在第二行中,该行仍然是c

中的原始行元素