一文看懂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的迅猛发展,其消息格式也在 ...
随机推荐
- Redis巡检检查 redis-check-aof
一.AOF1.AOF 是什么以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据,换言之,R ...
- 让摄像头带上智慧“智驭视界·AIEye”
接上一篇<物联网浏览器(IoTBrowser)-基于计算机视觉开发的应用"智慧眼AIEye">,经过AI的包装很高级,确实很屌炸天. 智驭视界·AIEye 在科技赋能的 ...
- oeasy教您玩转vim - 2 - # 使用帮助
回忆上节课内容 更新和运行 vim 进入和退出 vim 存活了下来 从中我们知道 vim 有两种模式:正常模式(Normal mode)和命令行模式 (Command-Line mode) 为了您能更 ...
- ICPC游记
\[\Large\color{#FCAEBD}『2024ICPC河南站 游记』 \] Day 0 晚上打了场 \(ABC\),快成屎了,最后竟然还加分了. 晚上回家洗了个澡,收拾收拾东西,凌晨2点就睡 ...
- DASCTF 2023六月挑战赛|二进制专项 PWN (上)
DASCTF 2023六月挑战赛|二进制专项 PWN (上) 1.easynote edit函数对长度没有检查 free函数存在UAF漏洞 思路:1.通过堆溢出,UAF,修改size位达到堆块重叠,使 ...
- php环境-2024年3月19日
laravel 6[laravel的orm比其他框架的好用,可以写很少的代码就能完成] php 7.4 mysql 5.7 centos7 redis jwt 队列(laravel的redis队列,或 ...
- java srpint boot 2.2.1 第二部份,乐观锁机制, 构造复杂查询条件,分页查询 相关内容,删除与软删除
第二部份,引起锁机制的原理和解决方案: 测试环境搭建第一步先建一个数据库表用于模拟商品购买. CREATE TABLE product ( id INT AUTO_INCREMENT PRIMARY ...
- mybatisplus实现一次多表联查+分页查询
众所周知,mybatisplus非常好用,但是他不好用就不好用在不可以多表联查.在mybatisplusjoin中提供了联查的方法,那个参数我没看懂Orz 不过,历经千辛万苦,我通过xml终于写出来了 ...
- Scratch全套Q版三国人物角色素材包免费下载
全新Q版三国人物角色素材包,内含142张细腻可爱的Q版风格图片,涵盖三国名将.士兵.场景等丰富元素,为scratch爱好者提供多样选择,适合各类三国主题创作. 免费下载:www.xiaohujing. ...
- 【Spring-Security】Re06 自定义Access & 注解权限分配
一.基于ACCESS方法处理的实现: 我们之前使用的任何放行规则的方法,本质上还是调用access方法执行的 这也意味之我们可以直接使用access方法去方向,只需要注入不同的字符串即可 自定义Acc ...