定义全局变量的方法Python,python中全局变量声明
你懂的都没问题。但我想谈谈这其中的原因。在说原因之前,我们需要知道python中变量的搜索顺序。这个顺序是LGB(不考虑闭包),也就是本地local,global global,builtin内置。例如:
a=1
定义测试():
a=3
打印(一份)
测试()
局部变量A在函数中声明,在打印中使用,在局部环境中命中,所以用3。
可能你会问我这个知识点。我已经知道了。和这个问题有什么关系?
是的,你不觉得很奇怪吗?错误是变量未初始化,而不是变量未定义。
标题函数中的C=c 1已经表明声明的变量c属于一个局部变量。按理说应该先执行赋值语句的右边,而C此时没有声明,所以应该在全局环境中命中。所以假想的结果应该是局部变量c=2,全局变量C保持原来的值。
然而,这只是理所当然的事。说了这么多,其实我想介绍的是,python虽然是动态语句,但还是会扫描代码,收集有用的静态信息。函数的预期信息将放在code对象中,里面的信息将包含一个局部变量名的集合,可以通过co_varnames获得,如下所示:
c=1
定义测试():
c=c 1
A=3 #另一个局部变量
打印(c)
打印(测试。__代码_ _。co_varnames) # (c , a )
所以,在函数测试执行之前,变量C已经在局部变量环境中声明了,而不是像我们想的那样,在赋值语句运行之后就在局部变量中。因此,错误消息是变量未初始化,而不是变量未定义。
======分割线======
主要意见要求:
能否帮助我们理解变量的初始化、定义和创建之间的关系?
这三个意思基本相同,没必要分的太开。其实把变量环境理解成字典name_env=dict()(其实python的底层确实是这样处理的)。要在这个环境中创建名为a的变量,可以采用name_env[a]=value的形式。
在这个过程中,当赋值语句像a=value时,会调用赋值指令STORE_NAME。我们来看看这个赋值流程,你就明白了。
这部分代码在ceval.c中,详情见ceval.c。
目标(商店名称){
PyObject *name=GETITEM(names,oparg);
py object * v=POP();
py object * ns=f-f _ locals;
int err
if (ns==NULL) {
PyErr_Format(PyExc_SystemError,
存储%R 时找不到局部变量,名称);
py _ DECREF(v);
goto错误;
}
if (PyDict_CheckExact(ns))
err=PyDict_SetItem(ns,name,v);
其他
err=PyObject_SetItem(ns,name,v);
py _ DECREF(v);
如果(呃!=0)
goto错误;
分派();
}
代码不多,可以一个一个分析。第一行获得的名称是赋值语句a=value的一个,A作为python类型str存在。第二行V是从栈中得到的,是value的值。第三行ns是从frame对象中获取局部变量环境(大多数情况下是字典类型,如果frame环境不在函数或类中,则是全局变量环境)。PyDict_SetItem(ns,name,v);和PyObject_SetItem(ns,name,v);可以理解为ns[name]=v和setattr(ns,name,v),创建过程是这样的。
变量是创建还是初始化还是覆盖已有的变量值,其实底层并不关心。
回到局部区域,局部变量的符号表将存储在静态信息中。我猜想在搜索变量时,我们优先从静态信息中获取信息,从而更快地知道变量应该局部搜索还是全局搜索。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。