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?
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 execution 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.