[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