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变量的更多相关文章

  1. 【转帖】一文看懂docker容器技术架构及其中的各个模块

    一文看懂docker容器技术架构及其中的各个模块 原创 波波说运维 2019-09-29 00:01:00 https://www.toutiao.com/a6740234030798602763/ ...

  2. 一文看懂Java序列化

    一文看懂Java序列化 简介 Java实现 Serializable 最基本情况 类的成员为引用 同一对象多次序列化 子父类引用序列化 可自定义的可序列化 Externalizable:强制自定义序列 ...

  3. 一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系

    我们知道,不同肤色的人外貌差别很大,而双胞胎的辨识很难.有意思的是Web服务器/Web容器/Web应用程序服务器/反向代理有点像四胞胎,在网络上经常一起出现.本文将带读者对这四个相似概念如何区分. 1 ...

  4. 一文看懂https如何保证数据传输的安全性的【转载、收藏】

    一文看懂https如何保证数据传输的安全性的   一文看懂https如何保证数据传输的安全性的 大家都知道,在客户端与服务器数据传输的过程中,http协议的传输是不安全的,也就是一般情况下http是明 ...

  5. [转帖]一文看懂web服务器、应用服务器、web容器、反向代理服务器区别与联系

    一文看懂web服务器.应用服务器.web容器.反向代理服务器区别与联系 https://www.cnblogs.com/vipyoumay/p/7455431.html 我们知道,不同肤色的人外貌差别 ...

  6. [转帖] 一文看懂:"边缘计算"究竟是什么?为何潜力无限?

    一文看懂:"边缘计算"究竟是什么?为何潜力无限? 转载cnbeta   云计算 雾计算 边缘计算...   知名创投调研机构CB Insights撰文详述了边缘计算的发展和应用前景 ...

  7. 一文看懂Stacking!(含Python代码)

    一文看懂Stacking!(含Python代码) https://mp.weixin.qq.com/s/faQNTGgBZdZyyZscdhjwUQ

  8. Nature 为引,一文看懂个体化肿瘤疫苗前世今生

    进入2017年,当红辣子鸡PD-1疗法,一路横扫多个适应症.而CAR-T治疗的“小车”在获得FDA专委会推荐后也已经走上高速路,成为免疫治疗又一里程碑事件.PD-1.CAR-T之后,下一个免疫治疗产品 ...

  9. 一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了

    一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了 转载: 大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它 ...

  10. 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变

    转载来自朱小厮博客的 一文看懂Kafka消息格式的演变     ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...

随机推荐

  1. Mac 设置多个版本JDK

    控制台: p.p1 { margin: 0; font: 11px Menlo; color: rgba(0, 0, 0, 1) } span.s1 { font-variant-ligatures: ...

  2. 咬文嚼图式的介绍二叉树、B树/B-树

    前言 因为本人天资愚钝,所以总喜欢将抽象化的事务具象化表达.对于各类眼花缭乱的树,只需要认知到它们只是一种数据结构,类似数组,切片,列表,映射等这些耳熟能详的词汇.对于一个数据结构而言,无非就是增删改 ...

  3. leetcode简单(矩阵):[566, 766, 832, 867, 999, 1030, 1261, 1275, 1337, 1351]

    目录 566. 重塑矩阵 766. 托普利茨矩阵 832. 翻转图像 867. 转置矩阵 999. 可以被一步捕获的棋子数 1030. 距离顺序排列矩阵单元格 1260. 二维网格迁移 1275. 找 ...

  4. Django+forms+html

    在Django中,Form类通常通过继承django.forms.Form或django.forms.ModelForm来定义.当你定义一个表单类时,通常使用Form或ModelForm类,并使用各种 ...

  5. 基于Java+SpringBoot+Vue宠物咖啡馆平台设计和实现

    \n文末获取源码联系 感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询 系统介绍: 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成 ...

  6. oeasy教您玩转vim - 67 - # 批量替换

    ​ 批量替换 回忆上次 我们可以用vimdiff快速的比较文件 这很实用!!! 实用的一些跳转方式 遍历所有的修改change ]c 下一条修改 [c 上一条修改 遍历所有的函数method ]m 下 ...

  7. Win10下安装LabelImg以及使用--LabelImg

    labelImg是图片标注软件,用于数据集的制作.标注等等.下面介绍labelImg的安装过程. 我用的是anaconda,所以以anaconda prompt作为终端: 在Anaconda Prom ...

  8. 《Programming from the Ground Up》阅读笔记:p75-p87

    <Programming from the Ground Up>学习第4天,p75-p87总结,总计13页. 一.技术总结 1.persistent data p75, Data whic ...

  9. [HTTP] HTTP 协议 Response Header 之 Content-Length、Transfer-Encoding与Content-Encoding

    0 引言 在近期项目一场景中,一 Web API (响应内容:7MB - 40MB.数据项:5W-20W条)的网络传输耗时较大,短则 5s,长则高达25s,前端渲染又需要耗时 9s-60s. 在这个场 ...

  10. 【Scala】08 模式匹配 Match Case

    由Scala封装的一套match case处理,功能比原Java的更为强大 package cn import scala.collection.immutable.IndexedSeqDefault ...