On Wed, Dec 5, 2012 at 10:34 AM, Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote: > The difference is almost certain between the LOAD_CONST and the > LOAD_GLOBAL. > > As to *why* there is such a difference, I believe that's a leftover from > early Python days when None was not a keyword and could be reassigned.
I think this should even be considered a bug, not just a missing optimization. Consider: >>> globals()['None'] = 42 >>> def f(x): ... return None ... print(x) ... >>> f('test') 42 The use of the LOAD_GLOBAL allows None to effectively be reassigned. It's also worth noting that: >>> def f(x): ... return ... print(x) ... >>> dis.dis(f) 2 0 LOAD_CONST 0 (None) 3 RETURN_VALUE 3 4 LOAD_GLOBAL 0 (print) 7 LOAD_FAST 0 (x) 10 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 13 POP_TOP So if you just write 'return' rather than 'return None', you get the correct bytecode. Additionally, the use of LOAD_GLOBAL instead of LOAD_CONST seems to be linked to having unreachable code at the end of the function. This is fine: >>> def f(x): ... if x: ... return None ... print(x) ... >>> dis.dis(f) 2 0 LOAD_FAST 0 (x) 3 POP_JUMP_IF_FALSE 10 3 6 LOAD_CONST 0 (None) 9 RETURN_VALUE 4 >> 10 LOAD_GLOBAL 1 (print) 13 LOAD_FAST 0 (x) 16 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 19 POP_TOP 20 LOAD_CONST 0 (None) 23 RETURN_VALUE But this is not. Note here that *both* loads of None become LOAD_GLOBAL in this case: >>> def f(x): ... if x: ... return None ... return None ... print(x) ... >>> dis.dis(f) 2 0 LOAD_FAST 0 (x) 3 POP_JUMP_IF_FALSE 13 3 6 LOAD_GLOBAL 0 (None) 9 RETURN_VALUE 10 JUMP_FORWARD 0 (to 13) 4 >> 13 LOAD_GLOBAL 0 (None) 16 RETURN_VALUE 5 17 LOAD_GLOBAL 1 (print) 20 LOAD_FAST 0 (x) 23 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 26 POP_TOP -- http://mail.python.org/mailman/listinfo/python-list