2013-03-10 54 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