[英]Pycharm - Disable 'Local variable 'xxx' might be referenced before assignment'
[英]PyCharm warns local variable might be referenced
为什么 PyCharm 突出显示boolean
变量附近的return
与Local variable "boolean" might be referenced before assignment
?
此代码检查数字是否为素数:
import random
import math
import time
def prime_t(x):
print x
if x < 2:
return False
if x == 2:
return True
if x == 3:
return True
for i in range(2, int(math.sqrt(x))+1):
if x % i == 0:
boolean = False
break
else:
boolean = True
return boolean
random.seed()
how_much = input()
start = time.time()
for i in range(0, how_much):
print(prime_t(random.randint(0, 1000)))
print time.time()-start
我读过这可能是全局变量的一些问题,但没有可能在prime_t()
中使用。 我有类似的事情 - 执行代码时出现异常,但我认为它已经被if x == 2
和if x == 3
消除了。
还有什么可能是问题?
PyCharm 不确定是否会设置boolean
。 计算代码流是不够智能的,所以它不知道你的for
循环总是至少有1次迭代 (因为那时x > 3
是真的)。
相反,它假定可能永远不会设置for
循环中绑定的变量,从而引发此警告。
解决方法当然是在循环之前设置boolean = False
,只是为了将其关闭。 这只是一个警告,你也可以忽略它,因为IDE试图帮助你,但却被误解了。
对于那些希望忽略这一点的人,把
# noinspection PyUnboundLocalVariable
在线以上。
感谢: https://github.com/whitews/pc-inspection-suppression-list/blob/master/suppress-inspection.csv
通常, for
或while
循环内的代码不必运行。 一旦最初达到循环,就可能不满足while
循环的条件。 for
循环可能会尝试遍历空的东西。 如果循环没有运行,并且循环中的代码是设置特定变量的唯一位置,那么它不会被设置。 尝试使用它会导致引发UnboundLocalError
( NameError
的子类型)。
IDE 通常会尝试检测这种情况并提供警告。 因为它们是警告,所以它们将是保守的。 Python 是一种高度动态的语言,在代码运行之前,您通常无法证明代码的行为。 因此,任何不使用常量、文字数据( for x in [1, 2, 3]:
)的循环都需要被视为“可能根本不会运行”。
而且,事实上,如果我在解释器提示符下尝试示例 function ,我可以很容易地得到UnboundLocalError
:
>>> prime_t(math.pi)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 14, in prime_t
UnboundLocalError: local variable 'boolean' referenced before assignment
毕竟,代码中没有其他任何东西对值进行类型检查; 并且 pi 不等于 3,也不等于 2,也不小于 2。
在上下文中,有几种合理的方法可以解决这个问题。
boolean = True
: boolean = True for i in range(2, int(math.sqrt(x))+1): if x % i == 0: boolean = False break return boolean
else
子句来设置“默认”值: for i in range(2, int(math.sqrt(x))+1): if x % i == 0: boolean = False break else: boolean = True return boolean
只要没有break
循环, else
块代码就会运行; 特别是,如果循环没有运行,它就会运行(因为没有什么可以break
的)。 所以 static 检查工具应该能够验证我们的基础是否被覆盖。 许多人不喜欢这种语法,因为它令人困惑并且经常是无意的(它看起来像一个错字,对吧?)。 然而,这种使用模式几乎正是它出现在语言中的原因。 (也就是说,我认为我们可以做得更好;继续阅读。)return False
,并在 function 的末尾return True
(因为如果我们走到这一步,我们还没有找到): for i in range(2, int(math.sqrt(x))+1): if x % i == 0: return False return True
(请注意,在所有这些情况下,我从if
中删除了else
- 因为它在这里没有用处。不断提醒自己我们还没有找到一个因素在逻辑上没有多大意义- 如果我们这样做了,我们就不会再循环了。)
综上所述,对于像这样的“搜索”循环,我更愿意完全避免显式for
循环。 内置的any
和all
函数实际上是为此目的而设计的——尤其是与生成器表达式配对时,它可以确保它们的短路行为保持相关:
return not any(x % i == 0 for i in range(2, int(math.sqrt(x))+1))
等效地(遵循德摩根定律):
return all(x % i != 0 for i in range(2, int(math.sqrt(x))+1))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.