Re: Quick question about CPython interpreter

2022-10-17 Thread Chris Angelico
On Tue, 18 Oct 2022 at 03:51, Stefan Ram  wrote:
>
> MRAB  writes:
> >It can't optimise that because, say, 'print' could've been bound to a
> >function that rebinds 'str'.
>
>   It would be possible to find out whether a call of a function
>   named "print" is to the standard function, but the overhead
>   to do this in the end might slow down the execution.
>
>   In general, it can be possible that there could be optimizer
>   stages after compilation. So, one might write a small micro-
>   benchmark to be sure.
>

You'd also have to ensure that the stringification of the ID doesn't
change (which it can it it isn't a core data type), and the easiest
way to do THAT is to call str() on the ID every time and see if it's
the same...

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Quick question about CPython interpreter

2022-10-17 Thread MRAB

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_NAME1 (range)
6 LOAD_CONST   1 (10)
8 CALL_FUNCTION1
   10 GET_ITER
  >>   12 FOR_ITER28 (to 42)
   14 STORE_NAME   2 (i)

3  16 LOAD_CONST   2 ('hi')
   18 LOAD_NAME3 (str)
   20 LOAD_NAME0 (thing)
   22 CALL_FUNCTION1
   24 COMPARE_OP   2 (==)
   26 POP_JUMP_IF_FALSE   12

4  28 LOAD_NAME4 (print)
   30 LOAD_CONST   3 ('found')
   32 CALL_FUNCTION1
   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_NAME1 (str)
6 LOAD_NAME0 (thing)
8 CALL_FUNCTION1
   10 STORE_NAME   2 (strthing)

3  12 LOAD_NAME3 (range)
   14 LOAD_CONST   1 (10)
   16 CALL_FUNCTION1
   18 GET_ITER
  >>   20 FOR_ITER24 (to 46)
   22 STORE_NAME   4 (i)

4  24 LOAD_CONST   2 ('hi')
   26 LOAD_NAME2 (strthing)
   28 COMPARE_OP   2 (==)
   30 POP_JUMP_IF_FALSE   20

5  32 LOAD_NAME5 (print)
   34 LOAD_CONST   3 ('found')
   36 CALL_FUNCTION1
   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


Re: Quick question about CPython interpreter

2022-10-17 Thread David Lowry-Duda
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_NAME1 (range)
  6 LOAD_CONST   1 (10)
  8 CALL_FUNCTION1
 10 GET_ITER
>>   12 FOR_ITER28 (to 42)
 14 STORE_NAME   2 (i)

  3  16 LOAD_CONST   2 ('hi')
 18 LOAD_NAME3 (str)
 20 LOAD_NAME0 (thing)
 22 CALL_FUNCTION1
 24 COMPARE_OP   2 (==)
 26 POP_JUMP_IF_FALSE   12

  4  28 LOAD_NAME4 (print)
 30 LOAD_CONST   3 ('found')
 32 CALL_FUNCTION1
 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_NAME1 (str)
  6 LOAD_NAME0 (thing)
  8 CALL_FUNCTION1
 10 STORE_NAME   2 (strthing)

  3  12 LOAD_NAME3 (range)
 14 LOAD_CONST   1 (10)
 16 CALL_FUNCTION1
 18 GET_ITER
>>   20 FOR_ITER24 (to 46)
 22 STORE_NAME   4 (i)

  4  24 LOAD_CONST   2 ('hi')
 26 LOAD_NAME2 (strthing)
 28 COMPARE_OP   2 (==)
 30 POP_JUMP_IF_FALSE   20

  5  32 LOAD_NAME5 (print)
 34 LOAD_CONST   3 ('found')
 36 CALL_FUNCTION1
 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.


- DLD
--
https://mail.python.org/mailman/listinfo/python-list


Re: Quick question about CPython interpreter

2022-10-17 Thread Michael Torrie
On 10/14/22 16:25, DFS wrote:
> -
> this does a str() conversion in the loop
> -
> for i in range(cells.count()):
>if text == str(ID):
>  break
> 
> 
> -
> this does one str() conversion before the loop
> -
> strID = str(ID)
> for i in range(cells.count()):
>if text == strID:
>  break
> 
> 
> But does CPython interpret the str() conversion away and essentially do 
> it for me in the first example?

No.

You can use the dis module to show you what CPython is doing under the hood.
-- 
https://mail.python.org/mailman/listinfo/python-list


Quick question about CPython interpreter

2022-10-17 Thread DFS

-
this does a str() conversion in the loop
-
for i in range(cells.count()):
  if text == str(ID):
break


-
this does one str() conversion before the loop
-
strID = str(ID)
for i in range(cells.count()):
  if text == strID:
break


But does CPython interpret the str() conversion away and essentially do 
it for me in the first example?



--
https://mail.python.org/mailman/listinfo/python-list