Python UnboundLocalError:int vs list

Python UnboundLocalError:int vs list,python,Python,我知道这个错误消息已经讨论过很多次了,但我还没有找到以下解释: def random2(seed): x = seed def update(): x = ( x * 16807 ) % 2147483647 return x return update r = random2(17283945) print(r()) 这不起作用,因为通过返回函数[UnboundLocalError],变量x的作用域似乎丢失了。好啊但现在我发现这绝对没

我知道这个错误消息已经讨论过很多次了,但我还没有找到以下解释:

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

r = random2(17283945)
print(r())
这不起作用,因为通过返回函数[UnboundLocalError],变量x的作用域似乎丢失了。好啊但现在我发现这绝对没有问题

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)易变性有关,但这对我来说仍然没有多大意义


非常感谢。

当您在变量名称后添加赋值运算符(
=
)时,该变量将自动假定为本地变量。因为你试图在赋值之前引用它,所以你得到了错误


在第二个示例中,您从未将变量
x
赋给任何对象,您只是对其进行了适当的变异。

如果您使用的是Python 3,则可以使用
非局部x

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

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

在Python2中,我总是像您那样处理列表。

@volatility已经解释了为什么会发生这种情况,但为了便于参考,您可以编写一个类似的函数,避免使用生成器嵌套作用域

def random(seed):
    x = seed
    while True:
        x = ( x * 16807 ) % 2147483647
        yield x
这将给你一个伪随机数序列,当你像随机(100)中的rand_num那样迭代时。您还可以根据需要获得新的随机数,而无需使用for循环:
rand\u gen=random(100);rand\u num=next(rand\u gen)


您可以看到,随机数生成器是生成器的自然用途:函数更短、更清晰,可以以自然的方式使用(
for…in
next
),并且不太容易出现由于
非本地
引起的错误。有关生成器和产量的更好解释,请参阅。非常感谢!我是Python新手,不知道有“nonlocal”关键字……但这并没有改变外部函数中的
x
,这意味着每次都会产生相同的数字。伪随机数生成器每次都会给你不同的数字,而不是一次又一次地给你相同的数字。啊,好的,我没在想。我想最好的办法是使用发电机——我会改变我的答案。