UnboundLocalError:int vs list

时间:2013-03-10 10:45:18

标签: python

我知道此错误消息已经讨论过很多但我没有找到以下解释:

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 个答案:

答案 0 :(得分:3)

当您在变量名称后面放置赋值运算符(=)时,该变量将自动假定为本地变量。因为你试图在它分配之前看似引用它,你会得到错误。

在第二个例子中,你从未向任何事物分配变量x,你只是在原地进行了变异。

答案 1 :(得分: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中,我总是按照列表执行的操作。

答案 2 :(得分: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