一文看懂global, nonlocal, local变量
Python中,变量是根据程序运行顺序进行的,比如函数外的变量,在函数内是可见的,但是可用,不可赋值。那么如何实现赋值呢?
利用global关键字进行。
在函数内,如果出现和函数外的变量同名变量,而且对这个变量进行了赋值操作,这个变量是局部变量,只对函数内可见。如果没有赋值操作,函数访问的是函数外的变量,此时如果你修改该变量将会提示报错,提示你在用这个变量前先进行赋值:UnboundLocalError: local variable 'x' referenced before assignment
也就是说,变量如果在函数内赋值,则这个变量是局部变量。而如果没有赋值操作,又没有加global关键字,使用的是外部的变量。而如果想对来自函数外部的变量进行操作,那么需要加global关键字。
在python内部,解释器引用变量的顺序是:1. 函数内的变量,2. 包含函数的区域 3.包含这个函数模块 4. 系统常用的比如len, str
# In[]
'''
global
nonlocal
#local
'''
x=10
def fun():
print(x) fun()
# In[]
'''
result:
10000
10
here x is a local variable, it is visible just in the function of fun(). It
has no relationship with the x variable outside.
'''
x=10
def fun():
x=10000
print(x) fun()
print(x) # In[]
'''
result:
UnboundLocalError: local variable 'x' referenced before assignment you can do assignment to the variable x, and it will be a local variable.
here the sentence 'x=x+1' is assignment but the x has not initialization.
''' x=10
def fun():
x=x+1
print(x) fun()
此时如果你的本意是对外部的变量进行修改操作,你只需要将这个变量设为global即可。
x=10
def fun():
global x
x=x+1
print(x) fun()
print(x)
另外,在函数嵌套中,也存在类似的问题。函数嵌套,一个函数内有另外一个函数。外部函数内的变量,对内部的函数是可见的。
def fun(x):
def inner(y):
print(x+y)
return inner f = fun(10)
f(1)
但是内部函数对外部函数内的变量是否可以修改呢?下面的代码会返回错误信息:UnboundLocalError: local variable 'x' referenced before assignment
def fun(x):
def inner(y):
# nonlocal x
x=x+10
print(x+y)
return inner f = fun(10)
print(f)
f(1)
但是当你把nonlocal这行注释取消了,就没有任何问题了。此时代码运行结果为21,10,说明在内部函数inner实现了变量x的增值x=x+10操作。这里变量x使用的是外部函数传入的参数,可以从程序里看到,此时外部的变量x在执行外函数调用后,并没有发生变化。外面打印x时,依然是10,而只有函数内部发生了变化。在函数fun中,x变量就是一个传入的参数,和外部的全局变量不一样的。
'''
You can not do assignment with the parameter x above.
But you can do this below.And it is not the same with global because
the variable x outside do not change. The change just appear in the function.
'''
x=10
def fun(x):
def inner(y):
nonlocal x
x=x+10
print(x+y)
return inner f = fun(x)
f(1)
print(x)
如果我用这个代码来写,可能会更加清晰了。就是说这里的nonlocal其实有点类似于前面的global的作用,只是范围不一样,但是达到的目的类似,就是使得更内一层的函数可以改变。
x=10
def fun(a):
def inner(y):
nonlocal a
a=a+10
print(a+y)
return inner f = fun(x)
f(1)
print(x)
nonlocal这个关键字出现在python3.x中,在python2是没有的。在python2中,可以通过可变对象类型比如list, dict来实现,内部函数对外部函数的变量进行改变。
'''
But nonlocal appears in python 3.5 later. Without nonlocal you can only use
list or dict, these variables is not like integer or str which can not vary.
Here you are not doing assignment actually.
'''
def fun(lst):
def inner(y):
lst.append(y)
print(len(lst))
return inner
lst = []
f = fun(lst)
f(1)
f(2)
f(3)
f(4)
这种做法,和以下做法一样。
def fun():
lst = []
def inner(y):
lst.append(y)
print(len(lst))
return inner f = fun()
f(1)
f(2)
f(3)
f(4)
但是如果是不可变对象,比如integer和str等就不可以了。python3引入nonlocal后,灵活多了。尤其是在闭包和装饰器中,使用非常灵活和方便。那么接下来的博客我将展开讲解闭包和装饰器。
好了,最后 思考题,通过这个题目,好好体会一下global和nonlocal的神奇。
x=10
def fun(a):
global x
x = 2
def inner(y):
# global x
nonlocal a
a=a + 10
x=a + y
print(x)
return inner f = fun(10)
f(1)
print(x)
此时,inner函数内部,注释掉一句后,输出结果是:
21
2
但是当你把注释拿掉,结果是:
21
21
这就是global的神奇之处,它对一层函数有效,在内部的函数,如果你不加global,x=a+y时x就是一个函数内的局部变量。那么如果函数嵌套有几层,内层是不是还需要再加一层global呢,试试吧?
一文看懂global, nonlocal, local变量的更多相关文章
- 【转帖】一文看懂docker容器技术架构及其中的各个模块
一文看懂docker容器技术架构及其中的各个模块 原创 波波说运维 2019-09-29 00:01:00 https://www.toutiao.com/a6740234030798602763/ ...
- 一文看懂Java序列化
一文看懂Java序列化 简介 Java实现 Serializable 最基本情况 类的成员为引用 同一对象多次序列化 子父类引用序列化 可自定义的可序列化 Externalizable:强制自定义序列 ...
- 一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系
我们知道,不同肤色的人外貌差别很大,而双胞胎的辨识很难.有意思的是Web服务器/Web容器/Web应用程序服务器/反向代理有点像四胞胎,在网络上经常一起出现.本文将带读者对这四个相似概念如何区分. 1 ...
- 一文看懂https如何保证数据传输的安全性的【转载、收藏】
一文看懂https如何保证数据传输的安全性的 一文看懂https如何保证数据传输的安全性的 大家都知道,在客户端与服务器数据传输的过程中,http协议的传输是不安全的,也就是一般情况下http是明 ...
- [转帖]一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系
一文看懂web服务器.应用服务器.web容器.反向代理服务器区别与联系 https://www.cnblogs.com/vipyoumay/p/7455431.html 我们知道,不同肤色的人外貌差别 ...
- [转帖] 一文看懂:"边缘计算"究竟是什么?为何潜力无限?
一文看懂:"边缘计算"究竟是什么?为何潜力无限? 转载cnbeta 云计算 雾计算 边缘计算... 知名创投调研机构CB Insights撰文详述了边缘计算的发展和应用前景 ...
- 一文看懂Stacking!(含Python代码)
一文看懂Stacking!(含Python代码) https://mp.weixin.qq.com/s/faQNTGgBZdZyyZscdhjwUQ
- Nature 为引,一文看懂个体化肿瘤疫苗前世今生
进入2017年,当红辣子鸡PD-1疗法,一路横扫多个适应症.而CAR-T治疗的“小车”在获得FDA专委会推荐后也已经走上高速路,成为免疫治疗又一里程碑事件.PD-1.CAR-T之后,下一个免疫治疗产品 ...
- 一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了
一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了 转载: 大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它 ...
- 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变
转载来自朱小厮博客的 一文看懂Kafka消息格式的演变 ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...
随机推荐
- Servlet3.0+SpringBoot2.X注解Listener常用监听器
监听器:应用启动监听器,会话监听器,请求监听器 作用: ServletContextListener 应用启动监听 HttpSessionLisener 会话监听 ServletRequestList ...
- 通俗讲解promise
JavaScript 中的 Promise 是一种特殊的对象,它用于解决异步编程中的复杂性问题,特别是回调的问题.我们可以把它比喻成现实生活中的一个"承诺": 想象一下,你 ...
- windows安装PHP的redis
一定要先看vc版本和位 配置php的redis扩展 以php7.3 nts版为例,不同的php版本对应不通的redis扩展:下载扩展文件:https://windows.php.net/downloa ...
- ModuleNotFoundError: No module named 'import_export'
当你遇到 "ModuleNotFoundError: No module named 'import_export'" 错误时,这表示你的 Python 脚本或应用程序试图导入名为 ...
- OpenFileDialog的使用实例
'Dim excelFolderPath As String = "" 'Dim openFileDialog1 As New OpenFileDialog() 'openFile ...
- 如何在.NET Framework,或NET8以前的项目中使用C# 12的新特性
前两天发了一篇关于模式匹配的文章,链接地址,有小伙伴提到使用.NET6没法体验 C#新特性的疑问, 其实呢只要本地的SDK源代码编译器能支持到的情况下(直接下载VS2022或者VS的最新preview ...
- AngleScript语法
Class的使用要继承于Interface或者Mixin class.Mixinclass实际上就是类似于抽象类 ,它已经实现的,在子类里面不能实现,类似如下代码: interface AInterf ...
- c++ 关于返回值、将亡值的调用研究
c++11引入右值引用,而出现右值引用的有这几种:返回值(将亡值),常量. class Obj { public: Obj() { cout << "构造函数" < ...
- 【超实用攻略】SpringBoot + validator 轻松实现全注解式的参数校验
一.故事背景 关于参数合法性验证的重要性就不多说了,即使前端对参数做了基本验证,后端依然也需要进行验证,以防不合规的数据直接进入服务器,如果不对其进行拦截,严重的甚至会造成系统直接崩溃! 本文结合自己 ...
- 深度解读GaussDB(for MySQL)与MySQL的COUNT查询并行优化策略
本文分享自华为云社区<[华为云MySQL技术专栏]GaussDB(for MySQL)与MySQL的COUNT查询并行优化策略>,作者:GaussDB 数据库. 1.背景介绍 统计表的行数 ...