[Raymond Hettinger]
def f(): None
dis(f) 2 0 LOAD_GLOBAL 0 (None) 3 POP_TOP 4 LOAD_CONST 0 (None) 7 RETURN_VALUE
None = 1 <stdin>:1: SyntaxWarning: assignment to None f() == None False
Is this a bug?
It's arguable, but it's always been this way, and is so boring that nobody has bothered to argue about it before <wink>. It's clear that explicit references to names must follow "the usual" name resolution rules, so you can't gripe about the LOAD_GLOBAL in this function: None is the name of a builtin, and in the language as currently defined, builtin names can be shadowed by globals or locals. What's arguable is the LOAD_CONST, which is generated for the implicit reference to None. The meaning of the Ref Man's A call always returns some value, possibly None, unless it raises an exception. How this value is computed depends on the type of the callable object. is arguably arguable, but I don't think *reasonably* so. To me it clearly intends "the" None, not whatever object you get by evaluating name "None" inside the callable. Likewise when it says the default value of object.__doc__ is None, I think it also clearly means "the" None.
Should the compiler use the GLOBAL in both places?
For backward compatibility it has to retain the LOAD_CONST. In this specific example, it doesn't matter whether the first is LOAD_CONST, or LOAD_GLOBAL, or simply thrown away, since the LOAD_GLOBAL 0 POP_TOP pair has no visible effect. If it were a more interesting function, like def f(): global aglobal aglobal = None then for backward compatibility it would have to remain LOAD_GLOBAL.
Or, is it reasonable to use CONST in both places?
Not today, but we should be moving in that direction. IMO, None should become a keyword.