Are nested ifs equals to and logic?

Advertisements

I wonder whether these two Python codes are always the same or not.

if condition_1:
    if condition_2:
        some_process

and

if condition_1 and condition_2:
    some_process

I searched but did not find any specific answer to this question. So, for example, you are trying to evaluate a variable, but you cannot determine if that variable exists. So, in the first place, you should check variable existence. Can we use the variable existence check with "and" logic alongside with our evaluation? Is it always applicable?

>Solution :

Yes, they are always equivalent. In fact, they compile down to the exact same bytecode, and only differ in some metadata1:

# Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]
# Type 'copyright', 'credits' or 'license' for more information
# IPython 7.31.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: def v1():
   ...:     if x:
   ...:         if y:
   ...:             pass
   ...: 

In [2]: def v2():
   ...:     if x and y:
   ...:         pass
   ...: 

In [3]: import dis

In [4]: dis.dis(v1)
  2           0 LOAD_GLOBAL              0 (x)
              2 POP_JUMP_IF_FALSE        7 (to 14)

  3           4 LOAD_GLOBAL              1 (y)
              6 POP_JUMP_IF_FALSE        9 (to 18)

  4           8 NOP
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE

  2     >>   14 LOAD_CONST               0 (None)
             16 RETURN_VALUE

  3     >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE

In [5]: dis.dis(v2)
  2           0 LOAD_GLOBAL              0 (x)
              2 POP_JUMP_IF_FALSE        7 (to 14)
              4 LOAD_GLOBAL              1 (y)
              6 POP_JUMP_IF_FALSE        9 (to 18)

  3           8 NOP
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE

  2     >>   14 LOAD_CONST               0 (None)
             16 RETURN_VALUE
        >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE

In [6]: v1.__code__.co_code == v2.__code__.co_code
Out[6]: True


1 Namely, the co_name, co_linetable, and co_lnotab attributes of the functions’ code objects, which do not affect the execute of the code. See the output of

import types
print( 
    {
        attr: (
            getattr(v1.__code__, attr),
            getattr(v2.__code__, attr),
        )
        for attr in dir(types.CodeType) if "co_" in attr
    }
)

for a detailed comparison of the functions’ respective code objects.

Leave a ReplyCancel reply