Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 82824) +++ Python/ceval.c (working copy) @@ -2052,6 +2052,7 @@ break; TARGET(LOAD_NAME) + TARGET(LOAD_NAME_LOCAL_ONLY) w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, @@ -2073,15 +2074,14 @@ } } if (x == NULL) { - x = PyDict_GetItem(f->f_globals, w); + if (opcode != LOAD_NAME_LOCAL_ONLY) { + x = PyDict_GetItem(f->f_globals, w); + if (x == NULL) + x = PyDict_GetItem(f->f_builtins, w); + } if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, w); - break; - } + format_exc_check_arg(PyExc_NameError, NAME_ERROR_MSG, w); + break; } Py_INCREF(x); } Index: Python/symtable.c =================================================================== --- Python/symtable.c (revision 82824) +++ Python/symtable.c (working copy) @@ -432,7 +432,12 @@ return PySet_Add(free, name) >= 0; } if (flags & DEF_BOUND) { - SET_SCOPE(scopes, name, LOCAL); + if (ste->ste_type == ClassBlock && bound && PySet_Contains(bound, name)) { + SET_SCOPE(scopes, name, LOCAL_ONLY); + } + else { + SET_SCOPE(scopes, name, LOCAL); + } if (PySet_Add(local, name) < 0) return 0; if (PySet_Discard(global, name) < 0) Index: Python/compile.c =================================================================== --- Python/compile.c (revision 82824) +++ Python/compile.c (working copy) @@ -787,6 +787,7 @@ case LOAD_CONST: return 1; case LOAD_NAME: + case LOAD_NAME_LOCAL_ONLY: return 1; case BUILD_TUPLE: case BUILD_LIST: @@ -2481,6 +2482,7 @@ optype = OP_DEREF; break; case LOCAL: + case LOCAL_ONLY: if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; @@ -2556,7 +2558,7 @@ break; case OP_NAME: switch (ctx) { - case Load: op = LOAD_NAME; break; + case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: Index: Include/opcode.h =================================================================== --- Include/opcode.h (revision 82824) +++ Include/opcode.h (working copy) @@ -123,6 +123,7 @@ #define LOAD_CLOSURE 135 /* Load free variable from closure */ #define LOAD_DEREF 136 /* Load and dereference from closure cell */ #define STORE_DEREF 137 /* Store into cell */ +#define LOAD_NAME_LOCAL_ONLY 138 /* The next 3 opcodes must be contiguous and satisfy (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1 */ Index: Include/symtable.h =================================================================== --- Include/symtable.h (revision 82824) +++ Include/symtable.h (working copy) @@ -88,6 +88,7 @@ #define GLOBAL_IMPLICIT 3 #define FREE 4 #define CELL 5 +#define LOCAL_ONLY 6 /* The following two names are used for the ste_unoptimized bit field */ #define OPT_IMPORT_STAR 1 Index: Lib/test/test_scope.py =================================================================== --- Lib/test/test_scope.py (revision 82824) +++ Lib/test/test_scope.py (working copy) @@ -690,7 +690,15 @@ h = g() self.assertEqual(h(), 3) + def testLocalClosureShadowing(self): + exec(""" +x = 4 +def f(x): + class C: + x = x +raises(NameError, f, 3)""", {"raises" : self.assertRaises}) + def test_main(): run_unittest(ScopeTests)