函数的进阶
一.函数嵌套
1. 函数的嵌套调用
def max(x,y): return x if x > y else y def max4(a,b,c,d): res1=max(a,b) res2=max(res1,c) res3=max(res2,d) return res3 print(max4(1,2,3,4))
2. 函数的嵌套定义
def f1(): def f2(): def f3(): print('from f3') f3() f2() f1() f3() #报错,为何?请看下一小节
二.名称空间与作用域
1.什么是名称空间?
#名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
2.名称空间的加载顺序
python test.py #1、python解释器先启动,因而首先加载的是:内置名称空间 #2、执行test.py文件,然后以文件为基础,加载全局名称空间 #3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
3.名字的查找顺序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
局部名称空间--->全局名称空间--->内置名称空间 #需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例 # max=1 def f1(): # max=2 def f2(): # max=3 print(max) f2() f1() print(max)
4. 作用域
#1、作用域即范围 - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效 - 局部范围(局部名称空间属于该范围):临时存活,局部有效 #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下 x=1 def f1(): def f2(): print(x) return f2 x=100 def f3(func): x=2 func() x=10000 f3(f1()) #3、查看作用域:globals(),locals() LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ locals 是函数内的名字空间,包括局部变量和形参 enclosing 外部嵌套函数的名字空间(闭包中常见) globals 全局变量,函数定义所在模块的名字空间 builtins 内置模块的名字空间
五,global和nonlocal关键字
global: 在局部访问全局中的内容(改变也是全局改变),找不到会在全局创建该变量
nonlocal: 在局部寻找外层函数中离他最近的那个变量,找不到会报错
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
b = 1 def func(): global a, b # 没有找到会在全局创建 a = 10 b = 20 print(a, b) # 10 20 func() print(a, b) # 10 20
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def outer(): a=3 def inner(): # 在inner中改变a的值 nonlocal a # 寻找外层函数中离他最近的那个变量,找不到会报错 a = 20 print(a) inner() print(a) outer()
练习:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
a = 1 def fun_1(): a = 2 def fun_2(): global a a = 3 def fun_3(): a = 4 print(a) print(a) fun_3() print(a) print(a) fun_2() print(a) print(a) fun_1() print(a)