2016-07-05 116 views
0

我有這個問題,我根據隨機性排序列表。算法的工作原理是兩個選擇一個介於0到N-1之間的隨機數(N是列表的長度)並與迭代索引交換。奇怪的輸出使用隨機python

我有這樣的兩種不同的算法。

import random 

def algo1(xx): 
    for i in xrange(len(xx)): 
     p = random.randrange(i, len(xx)) # random number between i and len(xx) - 1 
     xx[i], xx[p] = xx[p], xx[i] 
    return xx 

def algo2(yy): 
    for i in xrange(len(yy)): 
     p = random.randrange(0, len(yy)) # random number between 0 and len(xx) - 1 
     yy[i], yy[p] = yy[p], yy[i] 
    return yy 


k = range(5) 
print algo1(k) 
print algo2(k) 

這裏一切工作正常。我打印來自algo1和algo2的返回值。

但是,當我返回值存儲在變量

z1 = algo1(k) 
z2 = algo2(k) 
print z1 
print z2 

它們都包含相同的列表。多少次,我跑,他們表現出同樣的返回值

看到這部影片https://www.youtube.com/watch?v=ZBjlnaCLKsQ&feature=youtu.be

+0

我不明白你在做什麼,範圍(5)被傳遞給你的函數。 for循環的取值範圍(5)僅爲5,所以你的循環可能是'for xrange(5)':' –

+0

在調用之間移動print z1,它再次工作......沒有認真, 'assert id(z1)== id(z2)'會顯示,這些名字指向同一個列表,因此只保留最後一次修改。更改函數或將它們包裝在列表構造函數中,例如:'z1 = list(algo1(k))'或者製作一個像z1 = algo1(k)[:]'這樣的方法 - 這些方法應該能夠確定原因或症狀; - ) – Dilettant

回答

2

要修改的列表(我假設你是在Python 2.7版)代替。因此,當您將kalgo2混洗時,您也會影響z1。所有三個列表都是同一個對象。您需要創建一個列表副本,例如algo1(k[:])

我還會看看random.shuffle,它可以完成您想要的任務。請注意,random.shuffle也會修改輸入,因此您也需要[:]

2

您的功能改變了k並返回對它的引用。沒有新的list被創建。

在你所看到的所不同的是:

  • 當你打印,告訴你什麼algoX返回(這是k的引用)的當前狀態

  • 當你分配的結果,您可以設置z1z2k參考,這意味着z1 is z2 is k。而且你只有在完成操作後才能打印k。這就是爲什麼你看到結果相同,所有這3個變量都有相同參考到相同的列表。

1

當你傳遞,修改並返回相同的變量(列表)k這兩個函數,你每次修改相同的數據。

嘗試使用:

print("z1", id(z1)) 
print("z2", id(z2)) 
print("k", id(k)) 

這將返回變量的身份。你會注意到z1,z2和k都具有相同的標識。

在第一種情況下,您在調用下一個函數之前直接打印輸出。這就是爲什麼你沒有注意到這種行爲。

但是,當您分配返回變量,保存並打印它時,您會注意到該問題。

要解決它,而不是修改已傳入函數的列表,請在函數內部創建一個新列表,爲其分配值並返回該列表。

1

試試這個:

z1 = algo1(k) 
print z1 
z2 = algo2(k) 
print z2 
print z1 
print k 

你只是覆蓋相同的列表。谷歌的「python不可變vs可變類型」來理解這種行爲。