2013-03-10 55 views
3

我知道這個錯誤信息已經被討論了很多,但我還沒有發現下面的解釋:UnboundLocalError:INT VS名單

def random2(seed): 
    x = seed 
    def update(): 
     x = (x * 16807) % 2147483647 
     return x 
    return update 

r = random2(17283945) 
print(r()) 

這並不因爲變量的範圍工作x似乎通過返回函數[UnboundLocalError]而丟失。好。但現在我發現,這是絕對沒有問題

def random(seed): 
    x = [seed] 
    def update(): 
     x.append((x.pop() * 16807) % 2147483647) 
     return x[0] 
    return update 

r = random(17283945) 
print(r()) #580971270 
print(r()) #1923475628 
print(r()) #1783541505 

我有點困惑爲什麼,在這種情況下,x的範圍仍然有效。這似乎與(im)可變性有關,但這對我仍然沒有多大意義。

非常感謝。

回答

3

當您在變量名後加上賦值運算符(=)時,該變量會自動被認爲是本地變量。因爲您在嘗試在分配之前似乎參考它,所以會出現錯誤。

在第二個例子中,您從未將變量x分配給任何東西,您只是在原地進行了變異。

+0

非常感謝這個答案!現在情況正在變得更加清晰...... – ainu 2013-03-10 10:57:21

2

如果您正在使用Python 3,你可以使用nonlocal x

def random2(seed): 
    x = seed 
    def update(): 
     nonlocal x 
     x = (x * 16807) % 2147483647 
     return x 
    return update 

r = random2(17283945) 
print(r()) 

在Python 2我總是做你的名單做了什麼。

+1

非常感謝!我是新來的Python和以前不知道有「外地」關鍵字... – ainu 2013-03-10 10:59:42

0

@volatility已經解釋了爲什麼會發生這種情況,但爲了便於參考,您可以編寫一個類似的函數來避免使用生成器的嵌套作用域。

def random(seed): 
    x = seed 
    while True: 
     x = (x * 16807) % 2147483647 
     yield x 

當像for rand_num in random(100)迭代,這會給你的僞隨機數序列。您也可以在不使用for循環的情況下按需獲取新的隨機數:rand_gen = random(100); rand_num = next(rand_gen)

你可以看到,隨機數生成器是用於生成自然的使用:該功能是短,更清晰,可以以自然的方式(for...innext),不容易,可出現由於nonlocal的錯誤使用。有關生成器和yield的更好說明,請參見this question

+0

這不會改變在外部函數的'x'雖然 - 這意味着它會每次都產生相同數量。僞隨機數發生器每次給你不同的數字,而不是一遍又一遍。 – Volatility 2013-03-10 11:24:56

+0

啊,好點,我沒在想。我想最好的方法是使用一個發生器 - 我會改變我的答案。 – 2013-03-10 11:27:09