不是 Python 中的无测试 [重复]

Posted

技术标签:

【中文标题】不是 Python 中的无测试 [重复]【英文标题】:not None test in Python [duplicate] 【发布时间】:2011-04-27 06:40:38 【问题描述】:

在这些非无测试中。

if val != None:

if not (val is None):

if val is not None:

哪个更好,为什么?

【问题讨论】:

if val: 怎么样? 那不是同一个测试!如果 val 为 0、""、[]、0.0,则 if 将为 false。等等,如果它是无。 【参考方案1】:
if val is not None:
    # ...

是用于测试变量未设置为None 的Pythonic 习惯用法。这个成语在declaring keyword functions with default parameters 的情况下有特殊用途。 is 在 Python 中测试身份。因为在运行的 Python 脚本/程序中存在一个且只有一个 None 实例,所以 is 是对此的最佳测试。作为Johnsyweb points out,这在PEP 8 的“编程建议”下进行了讨论。

至于为什么首选这个

if not (val is None):
    # ...

这只是Zen of Python 的一部分:“可读性很重要。”好的 Python 往往接近于好的 pseudocode。

【讨论】:

另外,“is not”具有为此目的创建的特殊语义(这不是表达式构造的逻辑结果;“1 is (not None)”和“1 is not None”有两个不同的结果。 "not None" 返回 True。很有趣。 @gotgenes 并不总是正确的。例如:var = ''。如果您运行此代码,它将成功测试无。因此,您无法测试变量是否设置为 None 或空字符串。 @Ethan val = ''; print(val is not None) 打印出True,那么你发现哪一部分不正确? 至于为什么不推荐val != None:如果val 可以是None 或更复杂的东西,比如一个numpy 数组,这是否打算成为一个尚不完全清楚逐元素比较(例如:arr>0 将生成 arr 元素为正的索引列表),因此如果您希望 val 是数组或 None,那么 arr is None 是最安全的方法来测试一下。事实上,Python 2.7.6 会生成一个警告,指出 arr != None 将来会按元素工作。 arr is not None 也更易于阅读。【参考方案2】:

来自,编程建议,PEP 8:

应始终使用isis not 与诸如 None 之类的单例进行比较,而不应使用相等运算符。

另外,当您真正的意思是if x is not None 时,请注意不要写if x - 例如。在测试默认为 None 的变量或参数是否设置为其他值时。另一个值可能具有在布尔上下文中可能为 false 的类型(例如容器)!

PEP 8 是任何 Python 程序员的必备读物。

【讨论】:

【参考方案3】:

这类问题的最佳选择是确切了解 python 的作用。 dis 模块提供了令人难以置信的信息:

>>> import dis
>>> dis.dis("val != None")
  1           0 LOAD_NAME                0 (val)
              2 LOAD_CONST               0 (None)
              4 COMPARE_OP               3 (!=)
              6 RETURN_VALUE
>>> dis.dis("not (val is None)")
  1           0 LOAD_NAME                0 (val)
              2 LOAD_CONST               0 (None)
              4 COMPARE_OP               9 (is not)
              6 RETURN_VALUE
>>> dis.dis("val is not None")
  1           0 LOAD_NAME                0 (val)
              2 LOAD_CONST               0 (None)
              4 COMPARE_OP               9 (is not)
              6 RETURN_VALUE

请注意,最后两种情况简化为相同的操作序列,Python 读取not (val is None) 并使用is not operator。与None 比较时,第一个使用!= operator。

正如其他答案所指出的,在与None 进行比较时使用!= 是一个坏主意。

【讨论】:

compare_op 9 和 3 有什么区别? @evolvedmicrobe 从dis doc (https://docs.python.org/3/library/dis.html),COMPARE_OP 执行对应元组dis.cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD') 的布尔运算。所以COMPARE_OP 9 执行is notCOMPARE_OP 3 执行!=【参考方案4】:

后两者中的任何一个,因为val 可能属于定义__eq__() 以在传递None 时返回true 的类型。

【讨论】:

这是相当卑鄙的__eq__() 行为,我没有考虑过。捕捉角落案例的好答案。

以上是关于不是 Python 中的无测试 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python链式属性访问中的无传播[重复]

python单元测试中的assertRaises没有捕获异常[重复]

main中的无类型参数[重复]

Python统计列表中的重复项出现的次数

Python统计列表中的重复项出现的次数的方法

测试时间序列数据中的无戳记分钟