Python平等检查差异

假设当'a'和'b'都等于5时,我们需要执行一些代码块。然后我们可以这样写:

if a == 5 and b == 5: # do something 

但是前几天,我只是不由自主地写了一个类似的条件检查:

 if a == b and b == 5: # do something 

这让我想,两者有什么区别? 另外还有一个方法,

 if a == b == 5: # do something 

在评估或执行过程或所花时间方面是否有区别? 哪一个更好,哪个更好?

它是关于传递性的概念吗?

既然它们基本上是等价的,你也可以考虑你阅读/考虑代码的方式:

 if a == 5 and b == 5: # do something 

可以理解为“如果a等于5b等于5 ,那么…”。 你必须认为/结论 ,那么也将等于b

这与下一个例子相反:

 if a == b and b == 5: # do something 

作“如果a等于bb等于5 ”,你必须得出结论 ,那么a也将等于5

这就是为什么我更喜欢最后一个例子:

 if a == b == 5: # do something 

如果您熟悉Python (感谢Itzkata ),立刻就会明白,所有这三件事情必须相同(至5 )。 但是,如果在Python(但其他语言的编程技能)方面经验较less的人看到这一点,他们可能会对此进行评估

 if (a == b) == 5: 

它会比较第一次比较的布尔结果和整数5, 这不是Python所做的,可能导致不同的结果 (例如考虑a=0, b=0a==b==0是true,while (a==b) == 0不是!

手册说:

在Python中有八个比较操作。 它们都具有相同的优先级(这比布尔操作的优先级高)。 比较可以任意链接; 例如,x <y <= z相当于x <y和y <= z, 只不过y只计算一次 (但是在两种情况下,当x <y被发现为false时,根本不计算z)。

甚至可能会有所不同,例如,如果在您的示例中对b进行求和会产生副作用。

关于传递性,你是对的。

如果你有更多的variables要testing, all使用可能会稍微可读:

 if all(i==5 for i in [a,b,c,d]): # do something 

就整数而言,在前两个比较之间,就纯粹的性能来说,没有什么区别。

第三个比较是不同的, 因为更多地涉及到堆栈 。 的确,代码

 import dis def comparison_1(a, b): if a == 5 and b == 5: pass def comparison_2(a, b): if a == b and b == 5: pass def comparison_3(a, b): if a == b == 5: pass print("*** First comparison ***") dis.dis(comparison_1) print("\n*** Second comparison ***") dis.dis(comparison_2) print("\n*** Third comparison ***") dis.dis(comparison_3) 

回报

 *** First comparison *** 4 0 LOAD_FAST 0 (a) 3 LOAD_CONST 1 (5) 6 COMPARE_OP 2 (==) 9 POP_JUMP_IF_FALSE 27 12 LOAD_FAST 1 (b) 15 LOAD_CONST 1 (5) 18 COMPARE_OP 2 (==) 21 POP_JUMP_IF_FALSE 27 5 24 JUMP_FORWARD 0 (to 27) >> 27 LOAD_CONST 0 (None) 30 RETURN_VALUE *** Second comparison *** 8 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 COMPARE_OP 2 (==) 9 POP_JUMP_IF_FALSE 27 12 LOAD_FAST 1 (b) 15 LOAD_CONST 1 (5) 18 COMPARE_OP 2 (==) 21 POP_JUMP_IF_FALSE 27 9 24 JUMP_FORWARD 0 (to 27) >> 27 LOAD_CONST 0 (None) 30 RETURN_VALUE *** Third comparison *** 12 0 LOAD_FAST 0 (a) 3 LOAD_FAST 1 (b) 6 DUP_TOP 7 ROT_THREE 8 COMPARE_OP 2 (==) 11 JUMP_IF_FALSE_OR_POP 23 14 LOAD_CONST 1 (5) 17 COMPARE_OP 2 (==) 20 JUMP_FORWARD 2 (to 25) >> 23 ROT_TWO 24 POP_TOP >> 25 POP_JUMP_IF_FALSE 31 13 28 JUMP_FORWARD 0 (to 31) >> 31 LOAD_CONST 0 (None) 34 RETURN_VALUE 

这取决于。 你可以编写你自己的自定义__eq__ ,它可以让你比较自己的整数和事物:

  class NonNegativeInt(object): def __init__(self, value): if value < 0: raise Exception("Hey, what the...") self.value = value def __eq__(self, that): if isinstance(that, int): return self.value == that elif isinstance(that, NonNegativeInt): return self.value == that.value else: raise ArgumentError("Not an acceptible argument", "__eq__", that) 

根据比较“b”到“a”和“b”到“int”,这将工作不同。 因此, a == b可能是false,而a == 5 and b == 5可能是true。