Python == 在列表比较中与 or vs.的区别

6

在检查相等性时,以下两种方式的速度和功能是否有实际差异:

number = 'one'
if number == 'one' or number == 'two':

对比。

number = 'one'
if number in ['one', 'two']:

2
你使用了timeit吗?发生了什么?如果number='two'或为false-y的情况下会怎样?如果性能很重要,为什么不使用in {'one', 'two'} - jonrsharpe
2
我认为OP应该使用timeit并自己回答。然后我会给两个帖子点赞。 - Jay Calamari
使用集合比使用列表更快。因此,当您使用集合与if语句进行时间检查时。 - Grant Williams
1
@GrantWilliams: 只有在要测试的值的数量足够高时,set 才有帮助;对于两个值,set 是无济于事的。而且在这种情况下,OP 正在询问 Python 2,它不会优化 set 字面量中的测试,因此每次都必须从头开始重建 set,即使所有值都是字面常量,这将保证比创建全局常量的集合慢。在 Python 3 中,有一种优化方法可以用一个常量 frozenset 替换此上下文中的常量 set 字面量,因此可以在某些情况下节省时间,但在 Py2 中则不行。 - ShadowRanger
@JayCalamari 我运行了 timeit。之前不知道它。在那上面结果几乎相同。 - user2242044
@user2242044,太棒了,谢谢你的信息。也很有趣。 - Jay Calamari
2个回答

7
如果值是字面常量(如本例),则使用in可能会更快,因为(极其有限的)优化器将其转换为一次性加载的常量tuple,从而将执行的字节码工作减少到两个便宜的加载和单个比较操作/条件跳转,而链接的or包含每个测试的两个便宜的加载和一个比较操作/条件跳转。
对于两个值,可能不会帮助太多,但随着值的数量增加,与替代方案相比,字节码节省(特别是如果命中不常见或均匀分布在选项中)可能具有意义。
上述内容特别适用于CPython参考解释器;其他解释器可能具有更低的每字节码成本,从而减少或消除性能差异。
如果number是更复杂的表达式,则通常可以获得优势;my_expensive_function() in (...)显然优于my_expensive_function() == A or my_expensive_function() == B,因为前者只计算一次值。
尽管如此,如果tuple中的值不是常量文字,特别是如果命中将在早期值上普遍发生,则in通常会更昂贵(因为它必须每次都创建用于测试的序列,即使最终只测试第一个值)。

-1

NaN 的怪异行为值得注意,但它并不是一个“普遍的差异”(NaN 几乎是唯一的在比较时与自身不相等的数据类型)。就功能而言,number in ['one', 'two'] 等价于(除了值加载次数) number is 'one' or number == 'one' or number is 'two' or number == 'two'。对于字符串来说,这只是性能提升,而非行为上的差异。 - ShadowRanger
@ShadowRanger 如果我们在谈论字符串列表或其他默认类型的列表,我会同意你的观点。但是用户定义类的对象可以实现自己的__eq__,其中可以包括非平凡计算或关注相似对象是否相等 - 在这种情况下,检查is可能会改变行为。同样,对于重写__contains__的自定义容器(但我认为这是较少见的情况),也是如此。 - Eugene Primako

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接