2011-12-31 81 views
0

我遇到了一個Python 2.7的問題,令我瘋狂。非常奇怪的Python變量範圍行爲

我正在向一些函數傳遞一個數組,並且儘管變量被認爲是本地變量,但最終main變量的值被改變了。

我對Python有點新,但是這違背了我的任何常識。

任何想法我做錯了什麼?

def mutate(chromo): 
    # chooses random genes and mutates them randomly to 0 or 1 
    for gene in chromo: 
     for codon in gene: 
      for base in range(2): 
       codon[randint(0, len(codon)-1)] = randint(0, 1) 
    return chromo 

def mate(chromo1, chromo2): 
    return mutate([choice(pair) for pair in zip(chromo1, chromo2)]) 


if __name__ == '__main__': 
    # top 3 is a multidimensional array with 3 levels (in here I put just 2 for simplicity) 
    top3 = [[1, 0], [0, 0], [1, 1]] 

    offspring = [] 
    for item in top3: 
     offspring.append(mate(top3[0], item)) 

    # after this, top3 is diferent from before the for cycle 

UPDATE 因爲Python經過參考,我一定要在使用前陣列FO一個真正的副本,所以隊友功能必須改成:

import copy 
def mate(chromo1, chromo2): 
    return mutate([choice(pair) for pair in zip(copy.deepcopy(chromo1), copy.deepcopy(chromo2))]) 
+3

的可能的簡短的回答是有在Python中沒有「變量」,只有「名字」,這基本上意味着一切都是通過引用,甚至序列中的項目。 – 2011-12-31 00:56:45

+0

是的,我現在改變了。謝謝:) – jbssm 2011-12-31 00:57:42

+0

@jbssm:另外,請不要使用'from random import *'。出於充分的理由,這被認爲是不好的做法 – 2011-12-31 00:59:50

回答

1

你操縱chromo,你通過引用傳遞。因此,這些更改具有破壞性...因此return也是有意義的(codongenegenechromo)。我認爲你需要製作一份chromos的(深)副本。

+0

謝謝。所以,我需要在調用** mate **函數或另一個地方之前在** for循環中創建一個TMP副本? – jbssm 2011-12-31 01:06:52

+0

我會在mutate函數中創建一個副本,這樣你就可以保留你的結構,並且「返回」變得有意義。 – Nicolas78 2011-12-31 01:08:52

+0

好吧,在變異中出現了一些奇怪的現象:過了一段時間,我所有的向量都是相同的。 所以我把副本移到了隊友身上(使用'copy.deepcopy()'例程,它現在似乎正常工作。 – jbssm 2011-12-31 01:22:41

2

你遇到的問題源於python中的數組和字典通過引用傳遞的事實。這意味着,而不是一個新的副本由DEF創建和使用本地您得到一個指向存儲您的陣列...

x = [1,2,3,4] 

def mystery(someArray): 
    someArray.append(4) 
    print someArray 

mystery(x) 
[1, 2, 3, 4, 4] 

print x 
[1, 2, 3, 4, 4] 
+0

嗯,好吧,我應該在for循環中創建數組的副本?像:'對於top3中的項目: top3_tmp = top3 [0],itemTmp =項目 offspring.append(mate(top3_tmp,itemTmp))' – jbssm 2011-12-31 01:04:29

0

嘗試改變

offspring.append(隊友(TOP3 [ 0],項))至 offspring.append(伴侶(TOP3 [0] [:]項[:]))

,或者使用list()函數

+0

使用[:]它不起作用。我會看看我是否可以使用list() – jbssm 2011-12-31 01:13:22