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
等于5
, b
等于5
,那么…”。 你必须认为/结论 ,那么也将等于b
。
这与下一个例子相反:
if a == b and b == 5: # do something
这读作“如果a
等于b
和b
等于5
”,你必须得出结论 ,那么a
也将等于5
这就是为什么我更喜欢最后一个例子:
if a == b == 5: # do something
如果您熟悉Python (感谢Itzkata ),立刻就会明白,所有这三件事情必须相同(至5
)。 但是,如果在Python(但其他语言的编程技能)方面经验较less的人看到这一点,他们可能会对此进行评估
if (a == b) == 5:
它会比较第一次比较的布尔结果和整数5, 这不是Python所做的,可能导致不同的结果 (例如考虑a=0, b=0
: a==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。