1

今夜、ちょっとしたコードを書いていたとき、私はそれが私を止めることはありませんが、それを理解することができなかったために私の注意を引いたという問題に出くわしました. だからここに私が書いた関数があります(それを行うための最適な方法ではないはずですが、気にしないでください...)

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

テストサンプルを変更せずに取得します。おそらくそれは私が書いた関数から来ていますか?何も思いつきません...

だから私の質問があります:誰かが理由を知っていますか?

ありがとうございました :)

4

1 に答える 1

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

You keep creating a temporary line but its not the same reference as your original list c. You would actually need to affect the values inside of line for it to reflect the original object.

You could see it changing the values inside of that same line by doing:

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

Here is a way to visualize what is happening:

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

In the first one you can see that its always a temporary object. Whereas in the second, the line is still the original line element from your c

于 2012-08-09T01:08:48.700 に答える