一.闭包函数

如果内函数使用了外函数的局部变量,
并且外函数把内函数返回出来的过程,叫做闭包
里面的内函数是闭包函数

基本语法

def songyunjie_family():
	father = "王健林"
	def f_hobby():
		print(f_hobby)  # <function songyunjie_family.<locals>.f_hobby at 0x00000182EB9AA158>
		print("我们先定一个小目标,比如赚它一个亿,这是我爸爸{}".format(father))
	return f_hobby
func = songyunjie_family()
print(func)  # <function songyunjie_family.<locals>.f_hobby at 0x00000182EB9AA158>
func()  # 我们先定一个小目标,比如赚它一个亿,这是我爸爸王健林

复杂版本

def mashengping_family():
	father = "马云"
	jiejie_name = "马蓉"
	meimei_name = "马诺"
	money = 1000

	def jiejie():
		nonlocal  money
		money -= 700
		print("买包包,买名表,买首饰,把钱都败光了,家里的钱还剩下{}元".format(money))

	def meimei():
		nonlocal money
		money -= 200
		print("要找只找有钱人,宁愿在宝马里面哭,也不愿意在自行车上撒欢,家里的败光了还剩下{}元".format(money))
	def big_master():
		return (jiejie, meimei)

	return big_master

func = mashengping_family()
print(func)  # <function mashengping_family.<locals>.big_master at 0x0000020D0313DE18>
# 返回的是元组
tup = func()
print(tup)  # (<function mashengping_family.<locals>.jiejie at 0x0000020D0313DD08>, <function mashengping_family.<locals>.meimei at 0x0000020D0313DD90>)
# 获取姐姐
jiejie = tup[0]
# 获取妹妹
meimei = tup[1]

# big_master 是闭包函数,是直接被mashengping_family返回出来的
# jiejie,meimei是通过big_master间接被返回到函数外面的
# 调用妹妹
meimei()  # 要找只找有钱人,宁愿在宝马里面哭,也不愿意在自行车上撒欢,家里的败光了还剩下800元
# 调用姐姐
jiejie()  # 买包包,买名表,买首饰,把钱都败光了,家里的钱还剩下100元

二.获取闭包函数使用的变量 closure

res = func.__closure__

# cell_contents 用来获取单元格对象当中的闭包函数
jiejie = res[0].cell_contents
meimei = res[1].cell_contents
jiejie()  # 买包包,买名表,买首饰,把钱都败光了,家里的钱还剩下-600元
meimei()  # 要找只找有钱人,宁愿在宝马里面哭,也不愿意在自行车上撒欢,家里的败光了还剩下-800元

三.闭包的特征

内函数使用了外函数的局部变量
那么该变量与闭包函数发生绑定,
延长该变量的生命周期

def outer(val):
	def inner(num):
		return val + num
	return inner

func = outer(10)  # func = inner
res =  func(15)  # res = func(15) = inner(15)
print(res)  # 25

10实参 -> val形参
因为内函数inner是闭包函数,使用了外函数val
那么该函数val生命周期被延长,没有随着函数调用的结束而释放
res = inner(15) => return val + num => 10 +15 => 25

四.闭包的意义

模拟鼠标点击次数

num = 0
def click_num():
	global num
	num += 1
	print(num)

click_num()  # 1
click_num()  # 2
num = 100
click_num()  # 101
click_num()  # 102

使用闭包函数改写点击次数
闭包的意义:闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装的作用,外部无法访问

def click_num():
	num = 0
	def func():
		nonlocal num
		num += 1
		print(num)
	return func
func = click_num()
func()  # 1
func()  # 2
num = 1000
func()  # 3
func()  # 4
func()  # 5

五.匿名函数:用一句话表达只有返回值的函数

语法:lambda 参数: 返回值
追求代码:简洁,高效

1.无参的lambda表达式

def func():
	return "123"

# 改写
func = lambda : "123"
res = func()
print(res)  # 123

2.有参的lambda表达式

def func(n):
	return type(n)

# 改写
func = lambda n : type(n)
print(func([1, 2, 3]))  # <class 'list'>

3.带有判断条件的lambda表达式

在这里插入代码片
def func(n):
	if n % 2 == 0:
		return "偶数"
	else:
		return "奇数"

func = lambda n : "偶数" if n % 2 == 0 else "奇数"
res = func(17)
print(res)  # 奇数

六.三元(目)运算符

真值 if 条件表达式 else 假值 如果条件表达式为真,返回真值,否则返回假值

n = 16
res = "偶数" if n % 2 == 0 else "奇数"
print(res)  # 偶数

小练习 传递两个数,返回较大的那一个

def func(x, y):
	if x > y:
		return x
	else:
		return y
func = lambda x, y : x if x > y else y
res = func(200, 100)
print(res)  # 200