python函数的返回值、嵌套方式以及函数中的变量(一):https://developer.aliyun.com/article/1495711
函数的嵌套
互相嵌套的两个函数:
包裹在外层的叫做外函数,内层的就是内函数
def outer(): # inner() def inner(): print("我是inner函数")
在外层调用外层函数,如果外层函数没有打印,内层函数有打印,不执行内层函数的打印
在内部调用内部函数,才能打印
#(1)内部函数可以直接在函数外部调用么 不行
#inner()
#(2)调用外部函数后,内部函数可以在函数外部调用吗 不行
#outer()
#inner()
#(3)内部函数可以在函数内部调用吗 可以
outer()
#(4)内部函数在函数内部调用时,是否有先后顺序 有的
#先定义在调用
#在其他语言中有预加载的机制,提前把函数驻留到内存中,然后再去编译脚本内容
#python没有预加载函数的机制,只能先定义在调用;
#外函数是outer 中间函数是inner 最里层是smaller ,调用smaller函数
def outer(): def inner(): def smaller(): print("我是smaller函数") smaller() inner() outer()
#多层函数调用,只能层层都调用,才能显示出最内层函数内容,不能断层
以下调用才是正常的
LEGB 原则
def outer(): def inner(): def smaller(): print(a) smaller() inner() outer()
LEGB原则(就近找变量原则)
#找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间 (内建作用域)
G —— Global(module); 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
即便id未定义,但它是内置函数,在最内层也能调用
nonlocal的使用 (用来修改局部变量)
nonlocal遵循LEGB原则 nonlocal 只能修改局部变量
(1) 它会找当前空间上一层的变量进行修改
(2) 如果上一层空间没有,继续向上寻找
(3) 如果最后找不到,直接报错
(1)它会找当前空间上一层的变量进行修改
def outer(): a = 10 def inner(): nonlocal a a = 20 print(a) inner() print(a) outer()
(2)如果上一层空间没有,继续向上寻找
def outer(): a = 20 def inner(): a = 15 def smaller(): nonlocal a a = 30 print(a) smaller() print(a) inner() print(a) outer()
#如果有多层定义同一变量,nonloacl找到最近一层的变量,即不再向上寻找,只修改最近一层的变量
(3)如果最后找不到,直接报错
nonlocal 只能修改局部变量,不能修改全局变量
a = 20 def outer(): def inner(): def smaller(): nonlocal a a = 30 print(a) smaller() print(a) inner() print(a) outer()
error
如果在L,E层未找到该变量的定义,会直接报错
(4) 不通过nonlocal 是否可以修改局部变量呢?
def outer(): lst = [1,2,3] def inner(): lst[-1] = 3000 inner() print(lst) outer()
#使用nonlocal,如果多层都有这个变量的定义,只可以修改最近层变量的值
针对可变类型数据也一样,只修改最近层变量的值
不使用nonlocal,当变量是不可变类型,只能修改本层内的变量
不使用nonlocal,当变量是可变类型,可以直接修改各层数据
在使用nonlocal的层,不能再定义该变量