前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python3学习笔记 | 十九、Python的函数-作用域

Python3学习笔记 | 十九、Python的函数-作用域

作者头像
TeamsSix
发布2019-09-24 14:42:37
5570
发布2019-09-24 14:42:37
举报

部分设备阅读本文会存在代码错乱的情况,可点击阅读原文链接到博客中进行查看

一、Python作用域基础

作用域针对的是变量。在使用同一个变量名时,会出现作用域问题。如右边的x,在函数里与函数外是不同的变量。 • 一个def内定义的变量名能够被def内部使用。不能在函数外部引用这个变量名。 • def内的变量名与def外的变量名并不冲突。在def内赋值的与def外赋值的相同变量名是不同的变量。 变量名有如下三种不同作用域: 1、全局:在def外定义的变量名是全局变量 2、本地:在def内部定义的叫做本地变量 3、其它:嵌套def时,各自的变量也是独立的。

二、作用域法则

内嵌的模块是全局作用域,全局作用域的作用范围仅限于单个文件,每次的函数的调用都创建了一个新的本地作用域,赋值的变量名除非声明全局变量或非本地变量(Python3.x有非本地变量说法),否则均为本地变量。所有其它的变量名都可以归纳为本地、全局或者内置。

变量名使用时,查找顺序:LEGB L:本地变量名 - 在本地是否使用此变量名赋值过。 E:上一层结构中def或lambda的本地变量名 - 上一层是否使用此变量名赋值过。 G:全局变量名 - 在整个文件里是否对变量名赋值过。 B:内置变量名 - Python内部是否存在此变量名。 要是都找不到相应变量名,就会报错。

代码语言:javascript
复制
内置变量:exit、open等。
>>> l = 'global'; e = 'global'; g = 'global'  #全局变量
>>>def myenclosefunc():
...     e = 'enclose';l = 'enclose'  #enclose func变量
...     def mylocalfunc():
...             l = 'local'  #本地变量
...             print('in local: l={},e={},g={}'.format(l,e,g))
...     mylocalfunc()
...     print('in enclose: l={},e={},g={}'.format(l,e,g))
...
>>> myenclosefunc()
in local: l=local,e=enclose,g=global
in enclose: l=enclose,e=enclose,g=global
>>> print('in global: l={},e={},g={}'.format(l,e,g))
in global: l=global,e=global,g=global

三、global语句

在函数内,想改变全局变量,可以使用global语句来定义此变量为全局变量,如下所示。

代码语言:javascript
复制
>>> g = 'global'
>>> l = 'global'
>>> def myfunc():
...     global g
...     g = 'local'
...     l = 'local'
...
>>> g,l
('global', 'global')
>>> myfunc()
>>> g,l
('local', 'global')

在myfunc函数里,都重新赋值了g与l,但在函数执行后,只有g改变了。当使用global g 之后,当前函数里所使用的所有对变量g的更改都会对全局变量g进行更改。 除了这个方法,还有引用自己的方法(交互模式里,可以import main)与sys.modules的方法(可以使用引用过的所有模块,交互模式里本身可以用main方式),具体如下。

代码语言:javascript
复制
>>> x = 2
>>> import __main__
>>> __main__.x
2
>>> def glob():
...     __main__.x += 1
...
>>> glob()
>>> x
3
代码语言:javascript
复制
>>> x = 2
>>> import  sys
>>> sys.modules['__main__'].x
2
>>> def glob():
...     sys.modules['__main__'].x += 1
...
>>> glob()
>>> x
3

四、作用域与嵌套函数

被嵌套函数的作用域也是上级函数里:

代码语言:javascript
复制
>>> def outer():
...     def inner():
...             print('inner')
...

在这里,想调用inner函数,必须是在函数outer里面,不能直接使用。这个时候,我们可以返回内部函数的方法来提取内部函数:

代码语言:javascript
复制
>>> def outer():
...     def inner():
...             print('inner')
...     return inner()
...
>>> func1 = outer()
inner

工厂函数

工厂函数为:根据要求的对象,一个能够记住嵌套作用域的变量值的函数。这种功能,使用类可以更好的实现,但使用函数也能简单实现。

代码语言:javascript
复制
>>> def funcl(x):
...     def action(y):  #嵌套函数
...             return x ** y  #返回x ** y的值
...     return action  #返回嵌套的函数
...
>>> a = funcl(3)  #定义x值为3后的嵌套函数赋值
>>> a(2)
9
>>> a(3)
27

可以使用lambda,把之前函数变为:

代码语言:javascript
复制
>>> def func(x):
...     return lambda y :x ** y
...
>>> a = func(3)
>>> a(2)
9

关于lamdba的使用可以参考:https://www.cnblogs.com/evening/archive/2012/03/29/2423554.html

循环变量

代码语言:javascript
复制
>>> def makeAction():
...     acts = []
...     for i in range(5):
...             acts.append(lambda x:i ** x)
...     return acts
...

执行后,返回值可能不是我们想象的结果:

代码语言:javascript
复制
>>> funclist = makeAction()
>>> funclist[0](2)
16
>>> funclist[4](2)
16

原因在于,i x的时候,i的值取的是for循环结束后的最后一个(4)。我们需要写成lambda x, i=i: i x,这样,lambda里的i是本地变量,跟for循环里的i不冲突,优化后如下:

代码语言:javascript
复制
>>> def makeAction():
...     acts = []
...     for i in range(5):
...             acts.append(lambda x,i = i : i ** x)
...     return acts
...
>>> funclist = makeAction()
>>> funclist[0](2)
0
>>> funclist[2](2)
4
>>> funclist[4](2)
16

五、nonlocal语句

nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量,更多用法可以参考https://blog.csdn.net/youngbit007/article/details/64905070

代码语言:javascript
复制
>>> x = 1  #全局变量x为1
>>> y = 1  #全局变量y为1
>>> def printxy():  
...     x = 2  #printxy里的本地变量x为2
...     y = 2  #printxy里的本地变量y为2
...     def setxy():
...             nonlocal x  #设定x为nonlocal
...             global y  #设定y为global
...             x =3
...             y =3
...     setxy()
...     print(x)
...     print(y)
...
>>> printxy()
3  #printxy里的x为3
2  #printxy里的y没变,仍为2
>>> x,y
(1, 3)  #全局变量x没变,y变为3
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 TeamsSix 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Python作用域基础
  • 二、作用域法则
  • 三、global语句
  • 四、作用域与嵌套函数
    • 工厂函数
      • 循环变量
      • 五、nonlocal语句
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档