楼主: 北方Smile
1203 1

[CDA数据分析师学习之路] Python基础知识:什么是非局部语句? [推广有奖]

  • 0关注
  • 3粉丝

硕士生

15%

还不是VIP/贵宾

-

威望
0
论坛币
15 个
通用积分
0
学术水平
1 点
热心指数
1 点
信用等级
1 点
经验
883 点
帖子
84
精华
0
在线时间
16 小时
注册时间
2016-3-28
最后登录
2016-4-8

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

Python基础知识:什么是非局部语句?

有同学曾在微信中问小编什么是非局部语句(nonlocal statement),本文就是对此的回答,希望没有发的太晚。
非局部语句是Python 3.x中新引入的特性,可以让你给外层但非全局作用域中的变量赋值。官方文档中的说法是,非局部语句可以让所列的标识符(identifier)指向最近的嵌套作用域(enclosing scope)中已经绑定过的变量,全局变量除外。

如果没有非局部语句

一般来说,嵌套函数对于其外层作用域中的变量是有访问权限的。

[backcolor=rgb(238, 238, 238) !important][color=rgb(102, 102, 102) !important]












[color=rgb(170, 170, 170) !important]1


[color=rgb(170, 170, 170) !important]2


[color=rgb(170, 170, 170) !important]3


[color=rgb(170, 170, 170) !important]4


[color=rgb(170, 170, 170) !important]5


[color=rgb(170, 170, 170) !important]6


[color=rgb(170, 170, 170) !important]7


[color=rgb(170, 170, 170) !important]8


[color=rgb(170, 170, 170) !important]9


[color=rgb(170, 170, 170) !important]10


[color=rgb(170, 170, 170) !important]11


[color=rgb(170, 170, 170) !important]12



[color=rgb(0, 111, 224) !important]>>>[color=rgb(0, 111, 224) !important] [color=teal !important]def [color=teal !important]outside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important]:
[color=rgb(0, 111, 224) !important]        [color=rgb(0, 45, 122) !important]msg[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important] [color=rgb(221, 17, 68) !important]"Outside!"

[color=rgb(0, 111, 224) !important]        [color=teal !important]def [color=teal !important]inside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important]:
[color=rgb(0, 111, 224) !important]            [color=teal !important]print[color=rgb(51, 51, 51) !important]([color=rgb(0, 45, 122) !important]msg[color=rgb(51, 51, 51) !important])

[color=rgb(0, 111, 224) !important]        [color=teal !important]inside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])
[color=rgb(0, 111, 224) !important]        [color=teal !important]print[color=rgb(51, 51, 51) !important]([color=rgb(0, 45, 122) !important]msg[color=rgb(51, 51, 51) !important])

[color=rgb(0, 111, 224) !important]>>>[color=rgb(0, 111, 224) !important] [color=teal !important]outside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])
[color=rgb(0, 45, 122) !important]Outside[color=rgb(0, 111, 224) !important]!
[color=rgb(0, 45, 122) !important]Outside[color=rgb(0, 111, 224) !important]!





我们在outside函数中声明了msg变量,并赋值为“Outside!”。然后,在inside函数中打印msg的值。结果证明,inside成功获得了外层作用域中msg的值。

但是如果我们想给外层作用域中的变量赋值时,是不是按照平常的赋值操作就可以修改它的值呢?

[backcolor=rgb(238, 238, 238) !important][color=rgb(102, 102, 102) !important]












[color=rgb(170, 170, 170) !important]1


[color=rgb(170, 170, 170) !important]2


[color=rgb(170, 170, 170) !important]3


[color=rgb(170, 170, 170) !important]4


[color=rgb(170, 170, 170) !important]5


[color=rgb(170, 170, 170) !important]6


[color=rgb(170, 170, 170) !important]7


[color=rgb(170, 170, 170) !important]8


[color=rgb(170, 170, 170) !important]9


[color=rgb(170, 170, 170) !important]10


[color=rgb(170, 170, 170) !important]11



[color=rgb(0, 111, 224) !important]>>>[color=rgb(0, 111, 224) !important] [color=teal !important]def [color=teal !important]outside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important]:
[color=rgb(0, 111, 224) !important]        [color=rgb(0, 45, 122) !important]msg[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important] [color=rgb(221, 17, 68) !important]"Outside!"
[color=rgb(0, 111, 224) !important]        [color=teal !important]def [color=teal !important]inside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])[color=rgb(0, 111, 224) !important]:
[color=rgb(0, 111, 224) !important]            [color=rgb(0, 45, 122) !important]msg[color=rgb(0, 111, 224) !important] [color=rgb(0, 111, 224) !important]=[color=rgb(0, 111, 224) !important] [color=rgb(221, 17, 68) !important]"Inside!"
[color=rgb(0, 111, 224) !important]            [color=teal !important]print[color=rgb(51, 51, 51) !important]([color=rgb(0, 45, 122) !important]msg[color=rgb(51, 51, 51) !important])
[color=rgb(0, 111, 224) !important]        [color=teal !important]inside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])
[color=rgb(0, 111, 224) !important]        [color=teal !important]print[color=rgb(51, 51, 51) !important]([color=rgb(0, 45, 122) !important]msg[color=rgb(51, 51, 51) !important])

[color=rgb(0, 111, 224) !important]>>>[color=rgb(0, 111, 224) !important] [color=teal !important]outside[color=rgb(51, 51, 51) !important]([color=rgb(51, 51, 51) !important])
[color=rgb(0, 45, 122) !important]Inside[color=rgb(0, 111, 224) !important]![color=rgb(0, 111, 224) !important] [color=rgb(184, 92, 0) !important]# inside函数打印的msg
[color=rgb(0, 45, 122) !important]Outside[color=rgb(0, 111, 224) !important]![color=rgb(0, 111, 224) !important] [color=rgb(184, 92, 0) !important]# outside函数打印的msg





在inside函数中,我们想给msg变量赋值为”Inside!”。运行outside时,inside函数中msg的值为”Inside!”,但是在outside函数中却保留了原先的值!

之所以出现这个情况,是因为在inside函数中,Python实际上并没有为之前已经创建的msg变量赋值,而是在inside函数的局部作用域(local scope)中创建了一个名叫msg的新变量,但是这样就和外层作用域(outer scope)中的变量重名了。

这说明,嵌套函数对外层作用域中的变量其实只有只读访问权限。如果我们在这个示例中的inside函数的顶部再加一个print(msg)语句,那么就会出现UnboundLocalError: local variable 'msg' referenced before assignment这个错误。

非局部语句的引入,就是要尽量减少这种变量名冲突情况的出现,同时也让嵌套函数更加方便的操作外层函数中的变量。更加详细的原因,请看参考资料部分的PEP-3104。

转载地址:http://python.jobbole.com/84465/


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Python基础 python 基础知识 assignment IMPORTANT outside 基础知识 中新

沙发
北方Smile 发表于 2016-4-6 15:41:16 |只看作者 |坛友微信交流群
使用非局部语句之后

接下来,我们引入nonlocal语句。


1
2
3
4
5
6
7
8
9
10
11
12
>>> def outside():
        msg = "Outside!"
        def inside():
            nonlocal msg
            msg = "Inside!"
            print(msg)
        inside()
        print(msg)

>>> outside()
Inside!
Inside!
现在,我们在inside函数的顶部添加了nonlocal msg语句。这个语句的作用,就是告诉Python解释器在碰到为msg赋值的语句时,应该向外层作用域的变量赋值,而不是声明一个重名的新变量。这样,两个函数的打印结果就一致了。

nonlocal的用法和global非常类似,只是前者针对的是外层函数作用域的变量,后者针对的则是全局作用域的变量。

什么时候该使用非局部语句

有时候,你可能会疑惑什么时候才应该使用nonlocal。以下面的函数为例:


1
2
3
4
5
6
7
8
9
10
11
>>> def outside():
        d = {"outside": 1}
        def inside():
            d["inside"] = 2
            print(d)
        inside()
        print(d)

>>> outside()
{'inside': 2, 'outside': 1}
{'inside': 2, 'outside': 1}
你可能会想,因为没有使用nonlocal,inside函数中往字典d中插入的"inside": 2键值对(key-value pair)不会体现在outside函数中。你这么想挺合理,但却是错的。因为字典插入并不是赋值操作,而是方法调用(method call)。事实上,往字典中插入一个键值对相当于调用字典对象中的__setitem__方法。


1
2
3
4
>>> d = {}
>>> d.__setitem__("inside", 2)
>>> d
{'inside': 2}
所以,这个示例中我们可以不使用nonlocal,就能直接操作外层作用域中的变量。

小结

其实在许多Python程序中,很少用到非局部语句。但是,有了这种语句之后,我们就可以减少不同作用域之间变量名的冲突。非局部语句,也让我们更加容易地访问、操作外层作用域中的变量。不过,这在一定程度上也让语法变得更加复杂。

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-28 11:18