2019/09/30 03-global、nonlocal和闭包

在这里插入图片描述
函数有个作用范围,什么东西有作用域就是标识符,能否在某个环境应用标识符,就是是否能看见,这个范围就称为标识符的作用域

x=5在外部定义的,可以理解为全局的
如果想要外部使用函数内部的定义的变量是不被允许的,因为函数是一种封装,封装内部的东西在内部是不可见的

在这里插入图片描述
x=x+1,是赋值语句,相当在这个局部作用域赋值即重新定义,作用域在这个函数内部,这个x是重新定义,只能用在当前函数中,本身语法是允许的
赋值是先计算右边,x=x+1,,x没有定义
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在inner里面定义的不会影响外面的,等于在内部重新定义在这里插入图片描述在这里插入图片描述在这里插入图片描述
就想让里面想x=x+1,使用的x就是外面的x
现在是出现未绑定的本地变量的错误

在这里插入图片描述
使用global来解决,在foo函数的局部作用域里面,用到的所有x都当是全局的,就通知下面的x不要在本地定义,用全局定义,
x=5相当于在全局定义了变量X,,定义的函数用到了x=x+1(按照以前理解是生产本地变量,作用域就在函数内部)
global x 申明这个x不要在成为本地变量了,x就是全局的变量

在这里插入图片描述
下面的x=x+1 ,虽然是赋值即定义,但是已经说清楚了,不要用本地变量,而是使用外部的全局变量,在这里插入图片描述
全局定义应该优先放,global尽可能优先放,申明一般都放第一行,申明这个变量已经不属于这个局部作用域里了,是全局作用域变量在这里插入图片描述
里面的x是来自于全局的,把全局x来引用之后,又把x覆盖了,重新定义了x+1在这里插入图片描述
定义略过,foo调用在这里插入图片描述
**第8行没有定义,一个函数开启一个局部作用域,一个z不是全局变量
调用foo,
print 1,100
调用bar,全局z,不会再前面的局部找z,只会再外面找z,但是外面没有z
**在这里插入图片描述在这里插入图片描述在这里插入图片描述
这样写,再bar这个作用域没写明z的定义
里面的z要开辟新的作用域,就不是外面的z了
在这里插入图片描述
需要改成这样,两个global去掉一个都不行,都需要加上去,说明global也是有影响范围的
是代表当前作用域的z不在我的局部作用域定义了,是全局的,相当于z写在外面了
选中的这俩个,相当于第二行
在这里插入图片描述
foo调用开始从上往下,global z没问题
调用bar,申明global z,z=200定义好z的时候,z+1
在这里插入图片描述
global是在局部作用域中,后面的变量就不属于本地变量了,赋值和定义都相当于在全局作用域进行的
下面就相当于在全局作用域操作这个变量,只不过写在函数当中
z看是在函数中,但是因为有global,就定义在全局作用域中

在这里插入图片描述
在两个局部作用域分别用了global在这里插入图片描述
这两个z其实现在是一个意思在这里插入图片描述
global的影响范围只在当前作用域,把当前作用域的变量,操作起来相当于全局变量
global可以在局部作用域里面去申明某个变量已经不属于局部作用域了,是来自全局作用域的
函数是一个黑匣子,外部的变量尽量在函数中少用,函数在定义的时候应该要求传递参数来要求数据,而不是通过全局变量在里面引用,不要这么做
函数应该通过传参的方式把这些数据传进来,然后给你返回结果
尤其是全局变量应该反对使用
在这里插入图片描述
global是申明到了全局作用域
全局作用域中必须有x的定义
如果全局中没有x定义,就会报nameerror
在这里插入图片描述
使用global关键字的变量,将foo内的x声明为使用外部的全局作用域中定义的x
但是,x=10赋值即定义,在内部作用域为一个外部作用域的变量x赋值,不是在内部作用域定义个新变量,所以x+=1不会报错。
注意!这里x的作用域还是全局

在这里插入图片描述在这里插入图片描述
global的使用原则
在这里插入图片描述
如果要在局部作用域使用全局就使用global了
一般全局的定义,都属于公共的东西,大家都知道的设置成全局,否则不建议设置成全局变量,因为全局变量对于函数的影响太大,在内部都可见,所以在使用的时候可能带来各种问题
就算在外面定义了全局变量x=5,建议也不要轻易使用,所以一般全局变量设定常量,虽然python不能设定常量,但是会这么做

如果函数要使用外部全局变量,建议通过传参的方式,定义形参,传进来
不建议在函数中使用全局变量,除非明确知道自己在做什么,否则不推荐,要使用,也建议函数通过形参定义,实参传进来

不到万不得已,不用global
在这里插入图片描述
虽然global可以改变局部作用域,但是建议不使用,在标准库和别人写的,很少能看到global在这里插入图片描述
未在本地作用域中定义的变量,但却在外部作用域中定义的叫自由变量
比如,定义在内层函数外的外层函数的作用域中的变量

内部函数引用到了外部函数的变量z,这个变量称为自由变量
在这里插入图片描述
内层函数用到了外层函数,没说中间用了多少层,内层函数用到了外层函数的某些局部变量,这个局部变量称为自由变量

闭包是一个概念,在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包。很多语言都有这个概念,最熟悉就是javascript
在这里插入图片描述
内层的用到外层,这个例子已经产生闭包了,因为内存函数用到了外层函数的局部变量,所以闭包已经产生了。闭包的概念一定要有,因为讲到装饰器,基本上就玩不转了
在这里插入图片描述
内存函数用到了外层函数的自由变量,这时候就形成了闭包
在这里插入图片描述
函数调用不管,到下面,foo =counter()函数调用counter
第一行定义列表 c = [0]
函数定义跳过
return inc,inc标识符指代一个函数对象
所以foo = counter就返回一个inc函数 foo -》inc inc就是foo,这两个指向同一个内存对象
print 就是把 c[0]=c[0]+1 再返回 再调用

在这里插入图片描述
这里面,8,9,10,11这是全局的,全局的运行环境中foo没有消亡
foo没有消亡,相当于这个内存函数对象一直没有消亡
在这里插入图片描述
这个函数标识符被全局作用域里的foo记住了,除非你整个删除,全局作用域都结束了,否则foo指代inc这个函数对象,就一直保存着,
在这里插入图片描述
c要是消亡了,c[0]+=1就引用不到了
return c[0]就返回1
1+1 =2
然后c = 100
print(foo())打印出3
c =[0]跟全局没有任何关系
foo是等于counter里面执行完inc的返回值
inc不过是个标识符,这个函数对象在内存中,这个函数对象被赋值给了foo,引用计数+1
有foo在,这个引用计数部位0,这个inc函数就不会被清除,foo就指向内存中的地址了

在这里插入图片描述
inc就是引用,引用的就是内存地址
在这里插入图片描述
没有申明global,内外的c是两码事
c{0】是在c上找0的索引,本质上找的还是c

在这里插入图片描述
改成这样,圈出的部分定义在函数内部,但是操作的是全局变量,为了避免冲突
c控制在函数的作用域里面,这样和别人写代码就冲突少一些,所以global少用
(c现在是简单类型)
在这里插入图片描述
这是python2的技巧,(复杂类型引用的是内存地址)这里面有闭包,在python3提供了新的关键字,叫nonlocal在这里插入图片描述在这里插入图片描述
加上nonlocal,就出来了在这里插入图片描述
nonlocal不是本地的,不是inc这个函数的本地的,这个c不在这边定义在这里插入图片描述
global,只要是局部的定义值,可以在全局打印出来,来看看nonlocal作用的c能不能打印
new一个
这个局部作用域限定了c的作用域范围
nonlocal是本地,指的是inc整个函数的作用域

在这里插入图片描述在这里插入图片描述
nonlocal,这个c不在当前作用域定义,但是在外层的局部作用域定义,但不能是全局作用域在这里插入图片描述在这里插入图片描述
nonlocal定义,是在当前的作用域中这个变量,不在本地的局部作用域中定义,是来自外层的局部作用域中定义,(不能是全局作用域)
nonlocal不会去全局作用域找你,只在局部作用域解决这个问题,这是python3提供的新的keyword

列表实现,是借用的引用类型特点,这一块用简单的类型就实现了效果,而且还实现了闭包
(这个c不在本地申明,在外层申明)
这个里面的c,引用了外部定义好的c,就是内层函数用到了外层函数定义的自由变量,所以形成了闭包
内层函数使用到了外层函数的变量
在这里插入图片描述
内部传参的方式达到了内部c等于几的效果
这个地方的参数可以当局部变量来看,形参也是有用的,形参可以当作局部变量来看

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
如果这么用会报错,使用global来解决,来约束在局部的环境中在这里插入图片描述在这里插入图片描述nonlocal再往上找,就找到全局这一块了在这里插入图片描述
nonlocal不在本地作用域定义,而再上级的某一级局部作用域中定义,如果愿意还可以再嵌套,nonlocal会往上找,找到某一集之后,就认为是某个值了,如果往上找,发现没有,是绝对不会去全局作用域找的
nnonlocal是再找个当前级别往上找,一层层往外面找,如果能找到定义就拿来用,如果找不到就不会去全局作用域找,所以不能是全局作用域
在这里插入图片描述在这里插入图片描述
nonlocal是当前作用域中定义,是在当前作用域的外层去找,一层层找,找不到也不会去全局作用域去找,用nonlocal来帮助我们实现闭包

闭包是内层函数用到了外层函数的局部变量,用全局变量来做闭包不合适
嵌套函数的内层函数用到了外层函数的局部变量,就叫闭包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值