python - Local variable referenced before assignment

直接上代码

def foo():
	a = 1
	def bar():
		a = a + 1
	return bar()



运行foo(),报错


import dis
def foo():
	a = 1
	def bar():
		a = a + 1
	dis.dis(bar)
	return bar()

dis打印的内容如下:

python - Local variable referenced before assignment_第1张图片


很容易明白其意思,,应该是从某个地方加载a,1,执行加法,写回a;


CPython源码中,搜索“referenced before assignment



#define NAME_ERROR_MSG \
    "name '%.200s' is not defined"
#define GLOBAL_NAME_ERROR_MSG \
    "global name '%.200s' is not defined"
#define UNBOUNDLOCAL_ERROR_MSG \
    "local variable '%.200s' referenced before assignment"
#define UNBOUNDFREE_ERROR_MSG \
    "free variable '%.200s' referenced before assignment" \
    " in enclosing scope"

接着搜索UNBOUNDLOCAL_ERROR_MSG

TARGET(LOAD_FAST)
    x = GETLOCAL(oparg);
    if (x != NULL) {
        Py_INCREF(x);
        PUSH(x);
        FAST_DISPATCH();
    }
    format_exc_check_arg(PyExc_UnboundLocalError,
        UNBOUNDLOCAL_ERROR_MSG,
        PyTuple_GetItem(co->co_varnames, oparg));
    break;
TARGET(DELETE_FAST)
    x = GETLOCAL(oparg);
    if (x != NULL) {
        SETLOCAL(oparg, NULL);
        DISPATCH();
    }
    format_exc_check_arg(
        PyExc_UnboundLocalError,
        UNBOUNDLOCAL_ERROR_MSG,
        PyTuple_GetItem(co->co_varnames, oparg)
        );
    break;
static void
format_exc_unbound(PyCodeObject *co, int oparg)
{
    PyObject *name;
    /* Don't stomp existing exception */
    if (PyErr_Occurred())
        return;
    if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) {
        name = PyTuple_GET_ITEM(co->co_cellvars,
                                oparg);
        format_exc_check_arg(
            PyExc_UnboundLocalError,
            UNBOUNDLOCAL_ERROR_MSG,
            name);
    } else {
        name = PyTuple_GET_ITEM(co->co_freevars, oparg -
                                PyTuple_GET_SIZE(co->co_cellvars));
        format_exc_check_arg(PyExc_NameError,
                             UNBOUNDFREE_ERROR_MSG, name);
    }
}


初步判断是在执行LOAD_FAST时,报出的错误;

如果能够调试就好了,以后试试吧;

 

顺便提一下,CpythonDoc目录下有这样的解释



   >>> x = 10
   >>> def foo():
   ...     print(x)
   ...     x += 1


results in an UnboundLocalError:


   >>> foo()
   Traceback (most recent call last):
     ...
   UnboundLocalError: local variable 'x' referenced before assignment


This is because when you make an assignment to a variable in a scope, that
variable becomes local to that scope and shadows any similarly named variable
in the outer scope.  Since the last statement in foo assigns a new value to
``x``, the compiler recognizes it as a local variable.  Consequently when the
earlier ``print(x)`` attempts to print the uninitialized local variable and
an error results.





你可能感兴趣的:(编程语言,Python)