python2.7错误:UnboundLocalError:在赋值之前引用的局部变量'i'

时间:2013-11-13 18:28:20

标签: python python-2.7

运行此python脚本时出错。

def thousandthPrime():
    count=0
    candidate=5 #candidates for prime no. these are all odd no.s Since starts at 5 therefore we find 998th prime no. as 2 and 3 are already prime no.s
    while(True):
        #print 'Checking =',candidate
        for i in range(2,candidate/2): #if any number from 2 to candidate/2 can divide candidate with remainder = 0 then candidate is not a prime no.
            if(candidate%i==0):
                break
        if i==(candidate/2)-1: # If none divide it perfectly, i will reach candidate/2-1 eventually. So, this is a prime number.
            count+=1
            print 'No. of prime no.s found excluding 2 and 3 =',count, '--->',candidate
        if(count==998):
            print 'The thousandth prime is',candidate
            break
        candidate+=2 # to go to the next odd number.

我收到此错误:

File "/home/.../xxx.py", line 19, in thousandthPrime
    if i==(candidate/2)-1: # If none divide it perfectly, i will reach candidate/2-1 eventually. So, this is a prime number.
UnboundLocalError: local variable 'i' referenced before assignment

但是如果我替换候选人/ 2只是候选人,我没有错误,虽然它会增加一些不必要的计算。

3 个答案:

答案 0 :(得分:6)

您将candidate声明为整数。因此candidate/2也是一个整数,特别是2.然后,range(2, candidate/2)range(2, 2),这是什么都没有,所以i永远不会被初始化。您需要设置candidate=5.0以使其成为一个浮点数并且一切都应该很好。

修改 正如评论中指出的那样,简单地重新定义candidate会给你一个类型错误,但它应该足以让你走上正轨。注意,range(x, y)需要整数,您可能需要在使用int()进行除法或限制计算后再次转换为整数。此外,您可能想要了解为什么math.sqrt函数被提及与素性测试相关

答案 1 :(得分:0)

如果您单步执行,问题很简单:

>>> candidate=5
>>> candidate/2
2
>>> range(2, 2)
[]
>>> for i in []: print(i)
>>> i
NameError: name 'i' is not defined

你的循环是空的,所以你永远不会介入它,所以永远不会定义i

正如其他地方的评论中指出的那样,您实际上只需要检查int(sqrt(candidate)),而不是candidate/2。但如果你这样做,你仍然会遇到同样的问题:int(sqrt(5))仍然是2


这意味着这个测试:

if i==(candidate/2)-1:

...正在尝试访问尚未定义的变量。

但如果你退一步思考一下你真正在测试什么,那就是伪代码,就是这样:

if I finished the loop without break:

Python有一种内置的方式可以说:循环上的else子句。

事实上,介绍此功能的教程部分break and continue Statements, and else Clauses on Loops有一个与您的非常相似的示例:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print n, 'equals', x, '*', n/x
...             break
...     else:
...         # loop fell through without finding a factor
...         print n, 'is a prime number'

如果在没有else的情况下完成循环,将执行break子句 - 其中包括循环迭代器为空的情况。


所以,在你的代码中:

while(True):
    #print 'Checking =',candidate
    for i in range(2,candidate/2): #if any number from 2 to candidate/2 can divide candidate with remainder = 0 then candidate is not a prime no.
        if(candidate%i==0):
            break
    else: # If none divide it perfectly, i will reach candidate/2-1 eventually. So, this is a prime number.
        count+=1
        print 'No. of prime no.s found excluding 2 and 3 =',count, '--->',candidate

如果您想了解else的确切工作方式的详细信息,请参阅教程whilefor上的参考文档。

答案 2 :(得分:-1)

变量的范围

这个代码中没有问题,即使在预期范围之外使用变量i(在for构造内部)也没有问题,我应该在完成for循环后保持定义,提供...

检查边缘情况

...对于某些变量,for循环至少应运行声明名称i

由于没有发生这种情况,您将收到UnboundLocalError。

快速修复

你可以通过在for循环之前声明i变量来解决这个问题,以防它不能运行(一个简单的i = 2

建议步骤

正如Python Zen本身所说 explicit比隐式更好,通过对中断后想要保留的结果使用不同的变量,你可以使这个值显式而不是隐含到循环后的i变量。

示例:

def thousandthPrime():
    count = 0
    candidate = 5 # candidates for prime no. these are all odd no.s Since starts at 5 therefore we find 998th prime no. as 2 and 3 are already prime no.s
    while(True):
        # print 'Checking =',candidate
        useful_divider = 2
        for i in range(2, candidate / 2): # if any number from 2 to candidate/2 can divide candidate with remainder = 0 then candidate is not a prime no.
            if candidate % i == 0:
                useful_divider = i
                break
            if useful_divider == (candidate / 2) - 1: # If none divide it perfectly, useful_divider will reach candidate/2-1 eventually. So, this is a prime number.
            count+=1
            print 'No. of prime no.s found excluding 2 and 3 =',count, '--->',candidate
        # And so on...
        # ... and so on :)