11、函数的对象、函数的嵌套、名称空间与作用域、闭包函数
一、函数的对象
在python中,函数是第一类对象,函数是第一等公民
本质:函数可以当变量用
def func():
print('from func')
1、可以赋值
f=func
print(f)
f()
2、可以当做参数传给另一个函数
def foo(x):
print(x)
x()
foo(func)
3、可以当做函数的返回值
def foo(x):
return x
res = foo(func)
print(res)
4、可以当做容器类型的元素
l=[func,]
print(l)
l[0]()
例:
def withdraw(): print("提款") def tranfer(): print('转账') def check_balance(): print("查询余额") def save(): print("存款") func_dic = { "1": ["提款",withdraw], "2": ["转账",tranfer], "3": ["查询余额",check_balance], "4": ["存款",save] } while True: print("0 退出") for k,v in func_dic.items(): print(k,v[0]) choice = input(">>>: ").strip() if choice == '0': break if choice in func_dic: func_dic[choice][1]() else: print("输入错误")
二、函数的嵌套使用
def max2(x,y): if x > y: return x else: return y def max4(a,b,c,d): res1 = max2(a,b) res2 = max2(res1,c) res3 = max2(res2,d) return res3 print(max4(11,99,33,12))
函数的嵌套定义:
def f1(): x = 10 def f2(): print('from f2') print(x) print(f2) f1() # print(x) # print(f2)
三、名称空间及作用域
namespaces名称空间:存放名字的地方
内置名称空间:存放内置的名字
生命周期:python解释器启动则删除,关闭则销毁
全局名称空间:存放的是顶级的名字
生命周期:运行python文件则产生,python文件运行完毕则销毁
x = 10 y = 20 if 1 > 0: z = 30 with open('a.txt', mode='wt') as f: a = 333 while True: c = 444
局部名称空间:存放的是函数内的名字
生命周期:调用函数则产生,函数调用完毕则销毁
x = 10 def foo(m): # m = 111 n=222 # foo(111)
核心:名字的访问优先级
基于当前所在的位置向外查找
函数内-->外层函数-->。。。-->全局-->内置
LEGB
# 案例1 # len = 10 def func(): len = 20 # print(len) func() print(len) 案例2 def f1(): # x=555 def f2(): # x = 666 print(x) f2() x=444 f1()
名称空间与作用域的关系是在函数定义阶段(扫描语法时)就确立的,与什么时候调用及调用的位置无关
案例1 x = 111 def f1(): print(x) def f2(): x=222 f1() f2() 案例2 x = 111 def f1(): print(x) x = 222 f1()
作用域
全局作用域:内置名称空间+全局名空间
特点:全局存活,全局有效
局部作用域:局部名称空间
特点:临时存活,局部有效
global
案例1: l = [] def func(): # l.append(1111) l = [11,22,33] func() print(l) 案例2: x = 111 def func(): global x x = 222 func() print(x)
nonlocal
x = 111 def f1(): x = 222 def f2(): # global x # 生命变量名是来自于全局的 nonlocal x # 声明变量名是来自于外层函数的,不是全局 x = 333 f2() print(x) f1()
四、闭包函数
闭:指的该函数时定义在函数内的函数
包:指的就是该函数引用了一个外层函数作用域的名字
def outter(): x = 111 def wrapper(): print(x) return wrapper # 千万别括号 f = outter() # print(f) def foo(): x=222 f() foo()
为函数体代码传参的反感
方案一:直接用参数传
def wrapper(x): print(x) wrapper(111) wrapper(222) wrapper(333)
方案二:闭包
def outter(x): # x = 111 def wrapper(): print(x) return wrapper f1 = outter(111) f1() f2 = outter(222) f2()