PYTHON 中使用 GLOBAL引发的一系列问题


Posted in Python onOctober 12, 2016

哪里出问题了

python 中,使用 global 会将全局变量设为本函数可用。同时,在函数内部访问变量会先本地再全局。

在嵌套函数中,使用 global 会产生不合常理的行为。

上代码:

In [96]: def x():
b = 12
def y():
global a,b
a = 1
b = 2
y()
print "b =",b
....: 
In [97]: a = 111
In [98]: del b
In [99]: x()
b = 12
In [100]: a
Out[100]: 1
In [101]: b
Out[101]: 2

而在函数 x() 中,没有用 global,此时的b使用本地。所以 print 会打印本地 b

为什么会打印 12 ?还有 In[101]的 b 为 2 该怎么解释?

y(),使用的 global 竟然没把 x() 的 b = 12 导进来。

在函数 y() 中,语句 global a,b 使a,b扩展为全局,所以,在最高层,就算没有 b(In[98]),也会产生 b(In[101])。

也就是说, global a,b ,会认为 a 和 b 是最外层的变量。

再试一下:

In [102]: def x():
b = 12
def y():
global a,b
a = 1
y() 
print "b =",b
.....: 
In [103]: a = 111
In [104]: del b
In [105]: x()
b = 12
In [106]: a
Out[106]: 1
In [107]: b
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-107-3b5d5c371295> in <module>()
----> 1 b
NameError: name 'b' is not defined

报错了! y() global b 后没赋值,顶层就没有 b。这说明,global 只是引入名称,并不做赋值等操作。

global 不会管变量存不存在,只导入名称,对该名称的操作会反应到 ‘最高层名称空间‘。

再来:

In [109]: a = 111
In [110]: del b
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-110-745f2abe7045> in <module>()
----> 1 del b
NameError: name 'b' is not defined
In [111]: def x():
b = 12
def y():
global a,b
a = 1
print b
y()
print "b =",b
.....: 
In [112]: x()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-112-7354d77c61ac> in <module>()
----> 1 x()
<ipython-input-111-c05fc67a1e82> in x()
5 a = 1
6 print b
----> 7 y()
8 print "b =",b
9 
<ipython-input-111-c05fc67a1e82> in y()
4 global a,b
5 a = 1
----> 6 print b
7 y()
8 print "b =",b
NameError: global name 'b' is not defined

 这就确定了 内层y() 的 global 不会 导入 x() 的东西。

 那么,内层函数怎么使用正确的外层函数的变量呢?

解决内层函数参数传递问题

一、

首先,若只是取值,则不需要做任何处理。

In [119]: def x():
.....: a = 12
.....: def y():
.....: print a
.....: y()
.....: 
In [120]: x()
12
In [121]:

在 y() 中,一旦为 a 赋值,a 立马变内部变量。

In [121]: def x():
.....: a = 12
.....: def y():
.....: print "before a =",a
.....: a = 1
.....: print "then a =",a
.....: y()
.....: 
In [122]: x()
before a =---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-122-7354d77c61ac> in <module>()
----> 1 x()
<ipython-input-121-d8fbc0dba399> in x()
5 a = 1
6 print "then a =",a
----> 7 y()
8 
<ipython-input-121-d8fbc0dba399> in y()
2 a = 12
3 def y():
----> 4 print "before a =",a
5 a = 1
6 print "then a =",a
UnboundLocalError: local variable 'a' referenced before assignment

一旦在函数 y() 的某处给 a 赋值,则在赋值前,python 会认为 a 不存在。

同时发现 python2 的 print 会一个一个的 输出。鉴于此,我又在 python3 中试了,发现他是 一起输出。但这不是本文重点,折叠之。

In [7]: def x():
a = 1
def y():
print("before a=",a)
a = 10
print("then a=",a)
y()
...: 
In [8]: x()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-8-7354d77c61ac> in <module>()
----> 1 x()
<ipython-input-7-6e01e7317b24> in x()
a = 10
print("then a=",a)
----> 7 y()
<ipython-input-7-6e01e7317b24> in y()
a = 1
def y():
----> 4 print("before a=",a)
a = 10
print("then a=",a)
UnboundLocalError: local variable 'a' referenced before assignment

同时发现 python代码运行前 会先扫一遍代码的,而不是单纯的一行一行的执行。

同时发现返回 UnboundLocalError,而不是 NameError。注意到 'unbound‘,这是官方概念。用 'unbound‘ 来描述就是:global 会将顶层变量名称 绑定 到本地变量名称,同时变化,是为 '引用‘;python 检测到 a = 1时,意识到 a 是本地的,所以 在 a '指向一个对象‘(因为python变量均为引用),之前 ,调用 a 是非法 行为,但这种行为区别于于 NameError,就定义为 unbound local。

二、

使用 可变变量,如 list,dict

In [127]: def x():
.....: l = ["in msg"]
.....: def y():
.....: msg = l[0]
.....: print "msg =",msg
.....: l[:] = ["out msg"]
.....: y()
.....: print l[0]
.....: 
In [128]: x()
msg = in msg
out msg

没有报错,完美!

要注意 语句 l[:] = ["out msg"] ,使用切片赋值,否则,

In [129]: def x():
l = ["in msg"]
def y():
msg = l[0]
print "msg =",msg
l = ["out msg"]
y()
print l[0]
.....: 
In [130]: x()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-130-7354d77c61ac> in <module>()
----> 1 x()
<ipython-input-129-d44e750e285f> in x()
5 print "msg =",msg
6 l = ["out msg"]
----> 7 y()
8 print l[0]
9 
<ipython-input-129-d44e750e285f> in y()
2 l = ["in msg"]
3 def y():
----> 4 msg = l[0]
5 print "msg =",msg
6 l = ["out msg"]
UnboundLocalError: local variable 'l' referenced before assignment

又出 UnboundLocalError 了,因为 第六行代码 为 l 分配了 一个新的 list。

三、

利用参数传递。

In [136]: def x():
.....: a, b = 1, 2
.....: def y(a = a, b = b):
.....: a, b = 3, 4
.....: return a, b
.....: a, b = y()
.....: print a, b
.....: 
In [137]: x()
3 4

注意,不要在默认参数上放 list等可变对象。

以上所述是小编给大家介绍的PYTHON 中使用 GLOBAL引发的一系列问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
举例介绍Python中的25个隐藏特性
Mar 30 Python
Python使用dis模块把Python反编译为字节码的用法详解
Jun 14 Python
利用标准库fractions模块让Python支持分数类型的方法详解
Aug 11 Python
TF-IDF算法解析与Python实现方法详解
Nov 16 Python
python远程连接服务器MySQL数据库
Jul 02 Python
python多环境切换及pyenv使用过程详解
Sep 27 Python
pyinstaller还原python代码过程图解
Jan 08 Python
Python爬取365好书中小说代码实例
Feb 28 Python
python实现三壶谜题的示例详解
Nov 02 Python
class类在python中获取金融数据的实例方法
Dec 10 Python
python爬取豆瓣电影TOP250数据
May 23 Python
Python通过loop.run_in_executor执行同步代码 同步变为异步
Apr 11 Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
Oct 12 #Python
shelve  用来持久化任意的Python对象实例代码
Oct 12 #Python
Pyhton中单行和多行注释的使用方法及规范
Oct 11 #Python
使用Python脚本实现批量网站存活检测遇到问题及解决方法
Oct 11 #Python
深入浅析ImageMagick命令执行漏洞
Oct 11 #Python
Zabbix实现微信报警功能
Oct 09 #Python
python 2.6.6升级到python 2.7.x版本的方法
Oct 09 #Python
You might like
PHP程序61条面向对象分析设计的经验小结
2008/11/12 PHP
php实现评论回复删除功能
2017/05/23 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
jquery 事件对象属性小结
2010/04/27 Javascript
append和appendTo的区别以及appendChild用法
2013/12/24 Javascript
谈一谈js中的执行环境及作用域
2016/03/30 Javascript
BootStrap的Datepicker控件使用心得分享
2016/05/25 Javascript
JS实现简单的右下角弹出提示窗口完整实例
2016/06/21 Javascript
JavaScript实现相册弹窗功能(zepto.js)
2016/06/21 Javascript
JavaScript自学笔记(必看篇)
2016/06/23 Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
2016/09/04 Javascript
Bootstrap CSS布局之代码
2016/12/17 Javascript
Angular2 PrimeNG分页模块学习
2017/01/14 Javascript
手把手教你把nodejs部署到linux上跑出hello world
2017/06/19 NodeJs
es6中的解构赋值、扩展运算符和rest参数使用详解
2017/09/28 Javascript
微信小程序上传图片实例
2018/05/28 Javascript
javascript使用正则实现去掉字符串前面的所有0
2018/07/23 Javascript
微信小程序实现banner图轮播效果
2020/06/28 Javascript
微信小程序事件对象中e.target和e.currentTarget的区别详解
2019/05/08 Javascript
layui将table转化表单显示的方法(即table.render转为表单展示)
2019/09/24 Javascript
解决vue 给window添加和移除resize事件遇到的坑
2020/07/21 Javascript
vue使用lodop打印控件实现浏览器兼容打印的方法
2021/02/07 Vue.js
Python查询Mysql时返回字典结构的代码
2012/06/18 Python
如何运行Python程序的方法
2013/04/21 Python
Python控制多进程与多线程并发数总结
2016/10/26 Python
Python内存管理实例分析
2019/07/10 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
2020/06/04 Python
Python尾递归优化实现代码及原理详解
2020/10/09 Python
10个很棒的 CSS3 开发工具 推荐
2011/05/16 HTML / CSS
Sephora丝芙兰澳洲官方网站:国际知名化妆品购物
2016/10/27 全球购物
美国受欢迎的女性牛仔裤品牌:DL1961
2016/11/12 全球购物
医院护士的求职信
2014/01/03 职场文书
单位工作证明书格式
2014/10/04 职场文书
2014年少先队工作总结
2014/12/03 职场文书
清明节主题班会
2015/08/14 职场文书
CSS 实现角标效果的完整代码
2022/06/28 HTML / CSS