参考:http://www.opython.com/314.html
26 内嵌函数的执行
示例代码:
x = 0 # 全局变量
def outside(): # 定义函数
x = 1 # 局部变量,内嵌函数的外部变量
def inside(): # 定义内嵌函数
x = 2 # 局部变量
return x
return x, inside # 将变量值和函数返回
o, i = outside() # 通过两个变量接收outside函数的返回值x和inside
print(x) # 显示输出结果为:0
print(o) # 显示输出结果为:1
print(i()) # 显示输出结果为:2
在上方代码中,大家能够看到函数的返回值不仅可以返回多个,而且可以返回内嵌函数(这是闭包,后面会讲到)。
返回内嵌函数时,如果函数名称后方没有加上“()”,调用外层函数时不会立即执行返回的函数,需要在调用外层函数后,添加“()”来执行。例如,上方代码最后一句中的“i()”,就是执行变量中保存的函数。
而且,我们也可以用下面这种方法去执行返回的函数。
示例代码:
outside()[1]() # 调用外层函数时,获取的返回值列表中第2项是函数,加上()则会被执行。
这是外层函数有多个返回值时的方法,通过对外层函数返回值列表进行索引,找到函数执行。
如果,外层函数只有一个返回值,我们可以通过函数名称后方直接加上“()()”去执行返回的函数。
另外,在外层函数返回内嵌函数时,在函数名称后方加上了“()”,会在调用外层函数时自动执行。
对比如下两段代码
示例代码(返回函数不带括号):
def outside():
print('执行外层函数!')
def inside():
print('执行内嵌函数!')
return inside # 返回函数不带括号
outside() # 只执行外层函数outside(),打印 执行外层函数
示例代码(返回函数带括号):
def outside():
print('执行外层函数!')
def inside():
print('执行内嵌函数!')
return inside() # 返回函数带括号
outside() # 外层函数和内嵌函数同时执行,打印 执行外层函数,执行内嵌函数
27 Python作用域(命名空间)
Python 中作用域也叫命名空间,命名空间是一个我们看不到的字典,字典的键记录变量的名称,字典的值记录着变量的值。
每个模块都会创建一个全局命名空间,用于记录模块的变量,包括全局变量和局部变量,以及其它导入模块中的变量。
每个函数调用时都会创建一个局部命名空间,用于记录函数的变量,包括函数的参数和函数内部创建的变量。
另外,还有内置命名空间,任何模块都能够访问,记录了内置函数和异常。
28 全局变量的调用与修改
调用:在函数中创建的局部变量如果与全局变量同名,这时候如何调用全局变量
在函数中创建的局部变量如果与全局变量同名时,借用内置函数 globals 来获取到全局变量
示例代码:
def global_case(): # 定义函数
x = 5 # 创建同名局部变量
result = x * globals()['x'] # 通过globals函数获取全局变量x与局部变量x相乘
return result # 返回结果
print(global_case()) # 显示输出结果为:15
修改:如何在函数中修改全局变量(或者叫重新绑定全局变量为其他值)
使用 global 关键字,声明要重新绑定的全局变量,Python 解释器就能够知道,我们是要对已有的全局变量进行修改,而不是创建一个新的同名局部变量。
示例代码:
x = 10 # 创建全局变量
def change_global(): # 定义函数
global x # 声明要修改的全局变量
x = 5 # 修改变量值
change_global() # 调用函数
print(x) # 显示输出全局变量x的值,结果为:5
在上方代码中,大家能够看到,我们定义了全局变量x和修改这个全局变量的函数 change_global 。
在修改全局变量的函数 change_global 中我们并没有设定返回值,它只起到修改的作用。
所以,当我们执行了这个函数,再显示输出变量x的值,就是经过修改后的值
补充说明:如果想在内嵌函数中修改外层函数中的局部变量,可以使用关键字 nonlocal 进行声明。使用方法和关键字 global 类似。
示例代码:
def nonlocal_case():
x = 10 # 创建局部变量
def change_nonlocal(): # 定义函数
nonlocal x # 声明要修改的外部变量
x = 5 # 修改变量值
change_nonlocal() # 调用修改函数执行修改
return x # 返回变量x的值
print(nonlocal_case()) # 显示输出全局变量x的值,结果为:5
29 闭包(closure)
在网上查了闭包的解释,百度百科中是这样说的:闭包由要执行的代码块(内嵌函数)和为自由变量(外部变量)提供绑定的计算环境(作用域/命名空间)组成。
注意,上面这段话中,括号里面的内容是我按照自己的理解添加的。
以我个人的观点,闭包就是由返回的内嵌函数和这个内嵌函数中用到的外部变量(1)以及其他函数(2)打包而成的一个整体。
(1)外部变量,包括:外层函数的参数变量以及外层函数中定义的局部变量
(2)其它函数,包括:外层函数中定义的其他内嵌函数
例如,在本文第一段代码中就有闭包的出现。
为了更清楚的解释闭包的概念,我们来看一段代码。
用户输入合成的宝石数量,然后执行合成计算。
示例代码:
def synthesis():
count = int(input('请放入宝石:'))
while True:
if count < 3:
count += int(input('宝石太少,请再放入一些宝石:'))
else:
break
def execute():
result = count // 3 # 调用外部变量进行整除运算
print('您放入了%s颗宝石,合成了%s颗高级宝石!' % (count,result))
return execute
exe = synthesis() # 调用函数
print('------------------开始合成------------------')
exe() #执行闭包内容
这段代码中,外层函数被调用,执行return语句时,会将内嵌函数返回,形成闭包存入变量exe。
exe中的闭包内容包括:外层函数中变量count和内嵌函数excute。
exe()语句会执行闭包中的内容,我们可以认为执行了以下语句。
示例代码:
count = * # "*"表示外层函数执行后,变量count的最终值
def execute():
result = count // 3 # 调用外部变量进行整除运算
print('您的%s颗宝石,合成了%s颗高级宝石!' % (count, result))