繁体   English   中英

PyCharm 警告局部变量可能被引用

[英]PyCharm warns local variable might be referenced

为什么 PyCharm 突出显示boolean变量附近的returnLocal 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 == 2if 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

通常, forwhile循环内的代码不必运行。 一旦最初达到循环,就可能不满足while循环的条件。 for循环可能会尝试遍历空的东西。 如果循环没有运行,并且循环中的代码是设置特定变量的唯一位置,那么它不会被设置。 尝试使用它会导致引发UnboundLocalErrorNameError的子类型)。

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。


在上下文中,有几种合理的方法可以解决这个问题。

  1. 我们可以在循环之前简单地分配boolean = True
     boolean = True for i in range(2, int(math.sqrt(x))+1): if x % i == 0: boolean = False break return boolean
  2. 我们可以在循环中使用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 检查工具应该能够验证我们的基础是否被覆盖。 许多人不喜欢这种语法,因为它令人困惑并且经常是无意的(它看起来像一个错字,对吧?)。 然而,这种使用模式几乎正是它出现在语言中的原因 (也就是说,我认为我们可以做得更好;继续阅读。)
  3. 由于在 function 中的这个循环之后没有什么可做的,我们根本不需要标志; 我们可以在找到一个因子后立即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循环。 内置的anyall函数实际上是为此目的而设计的——尤其是与生成器表达式配对时,它可以确保它们的短路行为保持相关

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM