Python 相等检查差异

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23220141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:31:41  来源:igfitidea点击:

Python Equality Check Difference

python

提问by Vipul

Suppose we want some block of code to be executed when both 'a' and 'b' are equal to say 5. Then we can write like :

假设我们想要在 'a' 和 'b' 都等于 5 时执行一些代码块。那么我们可以这样写:

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

But a few days ago, I just involuntarily wrote a similar condition check as :

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

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

which made me think, is there any difference between the two ? Also, there is one other way,

这让我想到,两者之间有什么区别吗?另外,还有一种方法,

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

Is there any difference, any difference in terms of process of evaluation or execution or time taken ? and also which one is the better or which is better to use?

在评估或执行过程或花费的时间方面有什么区别吗?以及哪个更好或哪个更好用?

Is it related to the concept of transitivity ?

它与传递性的概念有关吗?

采纳答案by Jasper

Since they are basicallyequivalent, you could also consider the way you read/think about the code:

由于它们基本上是等效的,因此您还可以考虑阅读/思考代码的方式:

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

can be readas "if aequals 5and bequals 5, then do ...". You have to think/conclude, that then also awill be equal to b.

可以作“如果a等于5b等于5,那么做……”。您必须思考/得出结论,然后也a将等于b

This is opposite to the next example:

这与下一个示例相反:

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

This readsas "if ais equal to band bequal to 5" and you have to concludethat then also awill be equal to 5

作“如果a等于bb等于5”,您必须得出结论then 也a将等于5

This is why I prefer the last example:

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

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

If you are familiar with Python(thanks to Itzkata) it is immediately clear that all three things must be equal (to 5). If however people with less experience in Python (but programming skills in other languages) see this, they might evaluate this to

如果您熟悉 Python(感谢Itzkata),您会立即清楚所有三项必须相等(to 5)。然而,如果 Python 经验较少(但具有其他语言的编程技能)的人看到这一点,他们可能会对此进行评估

if (a == b) == 5:

which would compare the boolean result of the first comparison with the integer 5, which is not what Python does and might lead to different results(consider for example with a=0, b=0: a==b==0is true while (a==b) == 0is not!

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

The manualsays:

手册说:

There are eight comparison operations in Python. They all have the same priority (which is higher than that of the Boolean operations). Comparisons can be chained arbitrarily; for example, x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once(but in both cases z is not evaluated at all when x < y is found to be false).

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

There might even be a difference, for example if evaulating bin your example would have a side effect.

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

Regarding transitivity, you are right.

关于传递性,你是对的。

回答by wheaties

It depends. You could write your own custom __eq__which allows you to compare yourself to ints and things:

这取决于。您可以编写自己的自定义__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)

which would work different depending on comparing "b" to "a" and "b" to an "int." Hence, a == bcould be false while a == 5 and b == 5could be True.

根据将“b”与“a”和“b”与“int”进行比较,这会有所不同。因此,a == b可能为假而a == 5 and b == 5可能为真。

回答by Roberto Reale

As far as integers are concerned, there is no difference, in terms of sheer performance, between the first two comparisons.

就整数而言,就纯粹的性能而言,前两次比较之间没有区别。

The third comparison is different, though; since a little more fiddling with the stackgets involved. Indeed, the code

不过,第三个比较不同。因为涉及更多的堆栈操作。确实,代码

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)

returns

返回

*** 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        

回答by devnull

If you have more variables to test, using allmight be slightly more readable:

如果你有更多的变量要测试, usingall可能会稍微更具可读性:

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