nonlocal 意为:非局部的。
主要用于在函数内部定义函数时,内层函数使用外层函数的变量。(函数的函数——闭包,类比C++匿名函数的捕获列表)。
示例:
from typing import List
def func(nums: List[int], val:int):
def add():
nonlocal nums # 引用外层变量 nums
nums = [i+val for i in nums]
add() # 调用函数
print(nums) # 发现add函数调用之后,被引用的值也变了
func([1,2,3,4,5], 10)
输出结果为:[11, 12, 13, 14, 15]
如果我们将内层add() 函数以参数形式传递,则 外层函数的 nums 不会被修改
from typing import List
def func(nums: List[int], val:int):
def add(nums: List[int], val:int):
nums = [i+val for i in nums]
add(nums, val) # 调用函数
print(nums)
func([1,2,3,4,5], 10)
输出:[1, 2, 3, 4, 5]
我们发现使用 nonlocal 关键字可以让内嵌函数与父函数更好的“交流”,内层函数可以向外层函数获取数据,同时可以将数据修改后反馈给外层函数。
示例2:自增函数
def increase(start=0,step=1):
def add(): # 子函数,以step递增
nonlocal start
start += step # 递增
return start
return add
incr = increase(0) # 从0开始递增
print(incr())
print(incr())
print(incr())
print(incr())
# 输出 1 2 3 4
incr = increase(10,10) # 从10开始,每次递增10
print(incr())
print(incr())
print(incr())
print(incr())
# 输出 20 30 40 50
实现嵌套函数中,内外层函数的数据“交流”,如果不使用 nonlocal 关键字,就只能让内层函数通过返回值的方式将数据带出。
此外,也可以使用全局变量(使用global 声明),但这样一来就该全局变量就暴露在父函数的外部了,有被其他人修改的风险。
from typing import List
nums = [1,2,3,4]
def func(val:int):
def add():
global nums # 引用全局变量 nums
nums = [i+val for i in nums] # 修改全局变量 nums
add() # 调用函数
print(nums) # nums的值被修改
func(10)
print(nums) # 全局同用一个nums,该值为func中被修改的值
注意:nolocal 只能引用内层变量。
普通函数使用 nonlocal,error
内层函数使用nonlocal引用全局变量,error