You are partly right, but you are also missing a few things.
(1) Technically, the LOAD_* byte codes are implementation details, and there
is no requirement for Python interpreters to use them. In fact, Jython
being built on the JVM and IronPython being built on the .Net runtime
cannot use them. Even a C-based interpreter is not required to implement
name resolution in the same way.
(2) There are some odd corner cases in Python 2 where you use exec() or
import * inside a function to create local variables, where the CPython
interpreter no longer uses LOAD_FAST to resolve locals. (I'm going by
memory here, so I may have some of the details wrong.) You can experiment
with that if you like, but the behaviour has changed in Python 3 so its no
longer relevant except as a historical detail for those stuck on Python 2.
(To be precise, import * is forbidden inside functions, and exec() must take
an explicit namespace argument rather than implicitly applying to the local
function scope.)
(3) However, the most important case you've missed is code executed inside a
class namespace during class creation time:
class C(object):
a = 1
def test(): # intentionally no self
b = 2
return a + b
c = 3
d = test() + c
Don't forget classes nested inside classes...
I consider the LEGB rule to be a statement of intent, describing how a
Python implementation is expected to behave, *as if* it were following the
LEGB rule, not necessarily a statement of the implementation of any
specific Python implementation.
--
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.