3

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

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

非常感谢。

4

3 回答 3

3

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

在第二个示例中,您从未将变量分配x给任何东西,您只是在原地对其进行了变异。

于 2013-03-10T10:49:30.130 回答
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 中,我总是做你对列表所做的事情。

于 2013-03-10T10:49:51.263 回答
0

@volatility 已经解释了它发生的原因,但作为参考,这里是您如何编写一个类似的函数来避免使用生成器的嵌套范围。

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

当迭代 like 时,这将为您提供一系列伪随机数for rand_num in random(100)。您还可以在不使用 for 循环的情况下按需获取新的随机数rand_gen = random(100); rand_num = next(rand_gen)

您可以看到随机数生成器是生成器的自然用途:函数更短、更清晰,可以以自然的方式使用(for...innext),并且不太容易出现由于nonlocal. 有关生成器yield.

于 2013-03-10T11:22:59.200 回答