函数的嵌套
函数的嵌套
嵌套在函数的外边叫做外函数
嵌套在函数的里面叫做内函数
def outer():
# inner() error
def inner():
print("我是inner 函数")
inner()
outer()
inner()
(1)内部函数可以直接在函数外部调用么 不可以!
(2)调用外部函数后,内部函数可以在函数外部调用吗 不可以!
(3)内部函数可以在函数内部调用吗 可以
(4)内部函数在函数内部调用时,是否有先后顺序 有(必须先定义在调用)
最外层是outer , 中间层是inner , 最里层是smaller ,调用smaller ,执行里面的代码
def outer():
def inner():
def smaller():
print(id)
print("我是smaller函数")
smaller()
inner()
outer()
LEGB 原则 (即就近找变量的原则)
#找寻变量的调用顺序采用LEGB原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间 (内建作用域)
G —— Global(module); 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
### nonlocal 关键字 用来修改[局部变量]
nonlocal 遵循 LEGB
(1) nonlocal 专门用来修改当前作用域上一级的局部变量
(2) 如果上一级找不到,那么继续向上寻找
(3) 全都找不到,直接报错.
(1) nonlocal 专门用来修改当前作用域上一级的局部变量
def outer():
a = 10
def inner():
nonlocal a
a = 20
inner()
print(a)
outer()
(2)如果上一级找不到,那么继续向上寻找,nonlocal 只能修改局部变量
def outer():
a = 41
def inner():
def smaller():
nonlocal a
a = 42
print(a)
smaller()
print(a) # 41 or 42?
inner()
print(a)
outer()
(3) 全都找不到,直接报错.
a = 41
def outer():
def inner():
def smaller():
nonlocal a
a = 42
print(a)
smaller()
print(a) # 41 or 42?
inner()
print(a)
outer()
(4) 不使用nonlocal 是否可以修改局部变量呢?(通过将全部值放到列表里面)
def outer():
lst = [1,2,42]
def inner():
lst[-1] = 52
inner()
print(lst)
outer()
### 闭包函数
闭包函数:
内函数使用了外函数的局部变量
外函数将内函数返回出来的过程,叫做闭包
里面的内函数叫做闭包函数
(1) 闭包函数用法
def wz_family():
father = "王健林"
def wzj_hobby():
print("先定一个小目标,比如赚他一个亿,这是爸爸{}说的".format(father))
return wzj_hobby
res = wzj_hobby <=> res() = wzj_hobby()
res = wz_family()
print(res)
res()
(2) 升级
def weifuqiang_family():
father = "马1"
jiejie = "马2"
meimei = "马3"
money = 1000
def jiejie_hobby():
nonlocal money
money -= 700
print("爱包包,爱手表,爱经纪人,把家里的钱都败光了,还剩下%s元" % (money))
def meimei_hobby():
nonlocal money
money -= 200
print("我宁愿在宝马里面哭,在不愿意在自行车上面撒欢,家里的钱还剩下%s元" % (money))
def big_master():
return [jiejie_hobby,meimei_hobby]
return big_master
func = weifuqiang_family()
print(func)
lst = func()
print(lst)
#获取姐姐这个函数
jiejie = lst[0]
#获取妹妹这个函数
meimei = lst[1]
### 获取闭包函数使用的变量 closure , cell_contents(了解)
tup = func.__closure__
print(tup)
cell_contents 功能: 获取单元格对象里面的内容
jiejie = tup[0].cell_contents
meimei = tup[1].cell_contents
print(jiejie)
jiejie()
meimei()
### 闭包的特点
内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的生命周期
函数的定义处
参数也可以是局部变量
def outer(val):
def inner(num):
return num + val
return inner
函数的调用处
func = outer(5)
res = func(4)
print(res)
代码解析:
1.实参5 和 形参val 一一对应,进行接收 val = 5
因为内函数inner 和 val 进行绑定, 延长了val变量的生命周期,不释放
func = outer(5) < == > func = inner(inner返回成一个变量func)
2.实参4 和 形参num 一一对应,进行接收 num = 4
return num + val < == > 4 + 5 = 9
res = func(4) <==> return 9
res = 9
### 闭包的意义
闭包可以优先使用外函数的局部变量
局部变量在函数外部不能被直接使用
对局部变量实现了保护的作用,外部无法访问;
模拟鼠标点击操作
方法一
click_num = 0
def click_func():
global click_num
click_num += 1
print(click_num)
click_func() # 1
click_func() # 2
click_func() # 3
click_num = 100
click_func()
方法二
def outer():
click_num = 0
def inner():
nonlocal click_num
click_num += 1
print(click_num)
return inner
#click_func = inner
click_func = outer()
click_func()