使用 "if x in (y, z)" 会比 "if x == y or x == z" 更好吗?

Would it be better to use "if x in (y, z)" over "if x == y or x == z"?

鉴于这个简单的条件:

if x == y or x == z:
    print("Hello World!");

我知道 Python 会先看看 x 是否等于 y 并且 x 是否 等于 y 然后它会检查 x 是否等于 z,如果至少有一个条件是 True,则打印 Hello World!

如果我改为这样做:

if x in (y, z):
    print("Hello World!");

据我了解,Python 将遍历 "yz" 元组,然后如果 x 的值在 "yz" 元组中,则打印 Hello World!

哪种方法使用起来更快/更有效?
如果 x 等于 y,Python 会不会费心检查 x 是否等于 z
如果 x 等于 y z?[=31=,Python 是否仍会执行 if 语句中的代码]

提前谢谢你。

我愿意 if x == y or x == z:

  1. 您可以利用以下事实:如果 x == y.

    [=30,x == z 不会 被计算=]
  2. 创建匿名临时元组可能是一项开销。

  3. if x == y or x == z 在其他语言中也很常见,因此可能更具可读性。

也许好的 python 解释器可以优化匿名临时文件。

我知道python是个懒惰的语言,他不需要检查第二个语句。但是我不知道你的其他方法是否会更快。

Would Python not bother to check if x was equal to z if x was equal to y?

是的,Python不会检查它。

Would Python still execute the code in the if statement if x was equal to y but not z

不,他不会。

两个选择,第一个可读性更强,二十个,第二个。性能不是真正的问题。

让我们自己测试一下。

这里有一个 class 重载了相等运算符,让我们看看 Python 在做什么:

class Foo:
  def __init__(self, name):
    self.name = name

  def __eq__(self, other):
    print self.name, "==", other.name, "?"
    return self.name == other.name

让我们测试一下短路:

# x and a are passed the same string because we want x == a to be True
x = Foo("a")
a, b = Foo("a"), Foo("b")
if x in (a, b):
  print "Hello World!"

对我来说,输出:

a == a ?
Hello World!

a == b ? 未打印,因此短路确实按预期工作。该块也按需要执行。

现在是速度。如果我们将上面的 __eq__ 方法修改为 删除打印语句(以避免在我们的基准测试中使用 I/O) 并使用 IPython 的 %timeit 魔法命令,我们可以这样测试:

c = Foo("c") # for comparison when x is not equal to either case
%timeit x in (a, b) # equal to first case
%timeit (x == a or x == b)
%timeit x in (b, a) # equal to second case
%timeit (x == b or x == a)
%timeit x in (b, c) # not equal to either case
%timeit (x == b or x == c)

这些是每次迭代的平均次数(来自 100 万次迭代):

Code               Time (ns)
x in (a, b)        437
x == a or x == b   397
x in (b, a)        796
x == b or x == a   819
x in (b, c)        779
x == b or x == c   787

所以,相当可比的结果。有细微差别,但还不足以让您担心。根据具体情况使用最易读的那个。

当只有两个选项时,这实际上只是基于意见,但我想指出,如果您需要检查 x 与说 5 个值,将会有更大的差异:

if x == a or x == b or x == c or x == d or x == e:

对比:

if x in (a,b,c,d,e):

特别是如果您稍后需要将其更改为 not in 与所有 ==!= 相比,第二个似乎更容易扩展。