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

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