Python等式检查差异

Vip*_*pul 41 python

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

if a == 5 and b == 5:
    # do something
Run Code Online (Sandbox Code Playgroud)

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

if a == b and b == 5:
    # do something 
Run Code Online (Sandbox Code Playgroud)

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

if a == b == 5:
    # do something
Run Code Online (Sandbox Code Playgroud)

是否存在任何差异,评估或执行过程或所花费的时间有何不同?还有哪一个更好或哪个更好?

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

Jas*_*per 43

由于它们基本相同,您还可以考虑您阅读/思考代码的方式:

if a == 5 and b == 5:
  # do something
Run Code Online (Sandbox Code Playgroud)

可以作"如果a等于5b等于5,那么......".你必须思考/总结,那也a将等于b.

这与下一个例子相反:

if a == b and b == 5:
  # do something 
Run Code Online (Sandbox Code Playgroud)

作"if a等于bb等于5",你必须得出结论,那么它也a将等于5

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

if a == b == 5:
  # do something
Run Code Online (Sandbox Code Playgroud)

如果你熟悉Python(感谢Itzkata),很明显所有三件事都必须相同(to 5).然而,如果人们对Python经验不足(但其他语言的编程技能)看到了这一点,他们可能会对此进行评估

if (a == b) == 5:
Run Code Online (Sandbox Code Playgroud)

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

手册说:

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

甚至可能存在差异,例如,如果b在您的示例中进行评估会产生副作用.

关于传递性,你是对的.


dev*_*ull 20

如果您有更多要测试的变量,使用all可能会稍微更具可读性:

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


Rob*_*ale 15

就整数而言,在前两个比较之间,就纯粹的表现而言,没有区别.

但第三种比较是不同的; 因为更多的摆弄堆栈涉及到.的确,代码

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)
Run Code Online (Sandbox Code Playgroud)

回报

*** 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        
Run Code Online (Sandbox Code Playgroud)

  • 我很惊讶Python为第三次比较生成了如此复杂的代码...... (3认同)
  • 这是什么版本的Python? (2认同)

whe*_*ies 7

这取决于.您可以编写自己的自定义__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)
Run Code Online (Sandbox Code Playgroud)

根据将"b"与"a"和"b"与"int"进行比较,哪种方法会有所不同.因此,a == b可能是假的,而a == 5 and b == 5可能是真的.

  • 对于一个不专业的评论感到抱歉,但我认为"嘿,什么......鸭子"`将更加pythonic IMO =).无法自拔. (10认同)