Quick question about CPython interpreter
MRAB
python at mrabarnett.plus.com
Mon Oct 17 12:25:34 EDT 2022
On 2022-10-17 16:43, David Lowry-Duda wrote:
> One can use the `dis` module and investigate the generated python
> bytecode. For me, I get
>
> # file "dis1.py"
> thing = 123
> for i in range(10):
> if "hi" == str(thing):
> print("found")
> break
>
> The bytecode is then
>
> 1 0 LOAD_CONST 0 (123)
> 2 STORE_NAME 0 (thing)
>
> 2 4 LOAD_NAME 1 (range)
> 6 LOAD_CONST 1 (10)
> 8 CALL_FUNCTION 1
> 10 GET_ITER
> >> 12 FOR_ITER 28 (to 42)
> 14 STORE_NAME 2 (i)
>
> 3 16 LOAD_CONST 2 ('hi')
> 18 LOAD_NAME 3 (str)
> 20 LOAD_NAME 0 (thing)
> 22 CALL_FUNCTION 1
> 24 COMPARE_OP 2 (==)
> 26 POP_JUMP_IF_FALSE 12
>
> 4 28 LOAD_NAME 4 (print)
> 30 LOAD_CONST 3 ('found')
> 32 CALL_FUNCTION 1
> 34 POP_TOP
>
> 5 36 POP_TOP
> 38 JUMP_ABSOLUTE 42
> 40 JUMP_ABSOLUTE 12
> >> 42 LOAD_CONST 4 (None)
> 44 RETURN_VALUE
>
> I note that line 22 calls the function str repeatedly, and no
> optimization is done here.
>
> # file "dis2.py"
> thing = 123
> strthing = str(thing)
> for i in range(10):
> if "hi" == strthing:
> print("found")
> break
>
> This generates bytecode
>
> 1 0 LOAD_CONST 0 (123)
> 2 STORE_NAME 0 (thing)
>
> 2 4 LOAD_NAME 1 (str)
> 6 LOAD_NAME 0 (thing)
> 8 CALL_FUNCTION 1
> 10 STORE_NAME 2 (strthing)
>
> 3 12 LOAD_NAME 3 (range)
> 14 LOAD_CONST 1 (10)
> 16 CALL_FUNCTION 1
> 18 GET_ITER
> >> 20 FOR_ITER 24 (to 46)
> 22 STORE_NAME 4 (i)
>
> 4 24 LOAD_CONST 2 ('hi')
> 26 LOAD_NAME 2 (strthing)
> 28 COMPARE_OP 2 (==)
> 30 POP_JUMP_IF_FALSE 20
>
> 5 32 LOAD_NAME 5 (print)
> 34 LOAD_CONST 3 ('found')
> 36 CALL_FUNCTION 1
> 38 POP_TOP
>
> 6 40 POP_TOP
> 42 JUMP_ABSOLUTE 46
> 44 JUMP_ABSOLUTE 20
> >> 46 LOAD_CONST 4 (None)
> 48 RETURN_VALUE
>
> In short, it seems the cpython interpreter doesn't (currently) perform
> this sort of optimization.
>
It can't optimise that because, say, 'print' could've been bound to a
function that rebinds 'str'.
More information about the Python-list
mailing list