[Python-Dev] Don't set local variable in a list comprehension or generator

Victor Stinner victor.stinner at haypocalc.com
Thu May 19 12:34:29 CEST 2011


Le jeudi 19 mai 2011 à 10:47 +1200, Greg Ewing a écrit :
> Victor Stinner wrote:
> 
> >    squares = (x*x for x in range(10000))
> 
> What bytecode would you optimise that into?

I suppose that you have the current value of range(10000) on the stack:
DUP_TOP; BINARY_MULTIPLY; gives you the square. You don't need the x
variable (LOAD_FAST/STORE_FAST).

Full example using a function (instead of loop, so I need to load x):
-----------
import dis, opcode, struct

def f(x): return x*x

def patch_bytecode(f, bytecode):
    fcode = f.__code__
    code_type = type(f.__code__)
    new_code = code_type(
        fcode.co_argcount,
        fcode.co_kwonlyargcount,
        fcode.co_nlocals,
        fcode.co_stacksize,
        fcode.co_flags,
        bytecode,
        fcode.co_consts,
        fcode.co_names,
        fcode.co_varnames,
        fcode.co_filename,
        fcode.co_name,
        fcode.co_firstlineno,
        fcode.co_lnotab,
    )
    f.__code__ = new_code

print("Original:")
print("f(4) = %s" % f(4))
dis.dis(f)
print()

LOAD_FAST = opcode.opmap['LOAD_FAST']
DUP_TOP = opcode.opmap['DUP_TOP']
BINARY_MULTIPLY = opcode.opmap['BINARY_MULTIPLY']
RETURN_VALUE = opcode.opmap['RETURN_VALUE']

bytecode = struct.pack(
    '=BHBBB',
    LOAD_FAST, 0,
    DUP_TOP,
    BINARY_MULTIPLY,
    RETURN_VALUE)

print("Patched:")
patch_bytecode(f, bytecode)
print("f(4) patched = %s" % f(4))
dis.dis(f)
-----------

Output:
-----------
$ python3 square.py 
Original:
f(4) = 16
  3           0 LOAD_FAST                0 (x) 
              3 LOAD_FAST                0 (x) 
              6 BINARY_MULTIPLY      
              7 RETURN_VALUE         

Patched:
f(4) patched = 16
  3           0 LOAD_FAST                0 (x) 
              3 DUP_TOP              
              4 BINARY_MULTIPLY      
              5 RETURN_VALUE     
-----------

Victor



More information about the Python-Dev mailing list