python 全局变量_python 全局变量

理解的都没问题。但我想聊聊出现这种情况的原因。在讲原因之前,需要先知道python中变量的搜索顺序,这个顺序是 LGB (不考虑闭包情况)即local本地,global全局,builtin内建。比如:a = 1def test():

a = 3

print(a)

test()

函数内声明了局部变量 a ,在打印中使用,在本地环境中命中,因此使用的是 3。

也许你会问这个知识点我早就知道了,这和本问题有什么关系呢?

有的,难道你不觉得奇怪吗?报错是变量未初始化,而不是变量未定义。

题目中函数内 c= c+1 就已经表明了声明的变量 c 是属于局部变量的。 按理说,先执行赋值语句右侧,而此时 c 并没有声明,应该在全局环境命中才对啊。所以想象中的结果应该是局部变量 c = 2 而全局变量的 c 保持原值。

但是,这只都是想当然。讲了这么多其实我是想引出,python虽然是动态语句,但它还是会对代码做扫描工作的,会有收集有用的静态信息。函数的应该信息会放在 code 对象中,里面的信息就包含了局部变量名称的集合,可以通过 co_varnames 得到,如下:c = 1def test():

c= c+1

a = 3 # 另一个局部变量

print(c)

print(test.__code__.co_varnames) # ('c', 'a')

因此,函数test在执行前,变量 c 就已经被声明在局部变量环境中了,而不是我们自认为的当赋值语句运行后才会在局部变量里。于是,这就导致了报错信息是变量未初始化而不是变量未定义。

====== 分割线 =========

题主评论要求:关于变量的初始化,定义,创建这三者关系,能帮忙疏导一下理解吗?

这三个意思基本差不多,没必要分得太开。把变量环境理解成一个字典 name_env = dict() 其实就很好理解了(事实上python底层也确实是这样处理的)。对于在这个环境内要创建一个名为 a 的变量,就可以是 name_env['a'] = value 的形式了。

这个过程也就是赋值语句形如 a = value 时会调用赋值的指令 STORE_NAME 。我们看一下这个赋值过程你就理解了。

这部分代码在 ceval.c 中,详见 ceval.cTARGET(STORE_NAME) {

PyObject *name = GETITEM(names, oparg);

PyObject *v = POP();

PyObject *ns = f->f_locals; int err; if (ns == NULL) {

PyErr_Format(PyExc_SystemError, "no locals found when storing %R", name);

Py_DECREF(v); goto error;

} if (PyDict_CheckExact(ns)) err = PyDict_SetItem(ns, name, v); else

err = PyObject_SetItem(ns, name, v);

Py_DECREF(v); if (err != 0) goto error;

DISPATCH();

}

代码不多,可以逐个分析下,第一行获得的 name 就是赋值语句 a = value 的 a,a以python类型 str形式存在。第二行 v 从栈中获取,也就是 value 的值。第三行 ns 是从帧对象中获得局部变量环境(大多数情况下是个字典类型,如果帧环境不在函数或类中,取得的是全局变量环境)。PyDict_SetItem(ns, name, v); 和 PyObject_SetItem(ns, name, v); 就可以理解为 ns[name] = v 和 setattr(ns, name, v) 了,创建过程就是这样了。

变量究竟是创建还是初始化还是覆盖已有的变量值,其实底层并不关心。

回到本地中,本地变量的符号表会保存在静态信息里面,我猜测搜索变量时有优先去静态信息中得到信息,来更快的知道变量应该是在局部还是全局中查找吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值