函数嵌套、名称空间与作用域
函数的嵌套定义
# 概念:在一个函数的内部定义另一个函数 # 为什么要有函数的嵌套定义: 在函数内部调用其他函数 # 1)函数fn2想直接使用fn1函数的局部变量,可以将fn2直接定义到fn1的内部,这样fn2就可以直接访问fn1的变量 # 2)函数fn2名字就变成fn1的局部变量了,正常只能在fn1中使用,想在外部使用,可以将fn2函数对象作为fn1函数的返回值 # 3)在外部也用同名的变量fn2来接收fn1函数的执行结果(fn1函数的返回值),那么fn2也就是可以在外部被调用
名称空间
# 名称空间:存放变量名与变量值的内存地址得绑定关系的地方,可以被Python解释器遍历查找,采用堆栈存储方式 # 要想访问一个变量的值 必须先去名称空间中拿到对应的名字 才能够访问变量的值 # 三种名称空间 # Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁 # Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁 # Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁 # 注:文件中的if、while、for、with这些能产生缩减的关键字并不能产生名称空间 # 加载顺序:Built-in内置名称空间 > Global全局名称空间 > Local局部名称空间
作用域
# 作用域:变量(名字|对象)查找并起作用的范围 # 四种作用域 # LEGB # Built-in:内置作用域:名字在所有位置可见,作用所有文件的所有地方 # Global:全局作用域:名字在当前文件的任意位置可见,作用当前文件的所有地方 # Enclosing:嵌套作用域:名字在外层函数的局部与内部函数的局部可见,作用当前函数已内部被嵌套函数 # Local:局部作用域:名字只在局部可见,作用当前函数内部 # 注: # 不同作用域之间名字不冲突,以达到名字的重用 # 每个作用域优先使用自己作用域中的名字,没有再找更大的名称空间的名字,直到内置,还没有就报错 # 查找顺序:Local局部作用域 > Enclosing嵌套作用域 > Global全局作用域 > Built-in内置作用域
函数中名字查找顺序
名字的查找顺序 需要先确定你当前在哪 站在全局 全局名称空间 > 内置名称空间 站在局部 局部名空间 > 全局名称空间 > 内置名称空间
函数在定义阶段已经确定查找名字的顺序,不会因为函数的调用位置改变而改变
注意名字使用之前必须在查找的名字空间内先创建不能先使用后创建,不然报错
global关键字
# 作用:将局部的变量提升为全局变量 # 1.全局没有同名变量,直接提升局部变量为全局变量 # 2.有同名全局变量,就是统一全局与局部的同名变量 # -- 如果局部想改变全局变量的值(发生地址的变化),可以用global声明该变量 global 变量 如果想修改多个用逗号隔开变量
nonlocal关键字
# 作用:将局部的变量提升为嵌套局部变量 # 1.必须有同名嵌套局部变量,就是统一嵌套局部与局部的同名变量 # -- 如果局部想改变嵌套局部变量的值(发生地址的变化),可以用nonlocal声明该变量 nonlocal 变量 如果想修改多个用逗号隔开变量