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'.
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to