万事开头难

闭包

一. 概念

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

二、基本语法

def songyunjie_family():
    father = "王健林"
    def f_hobby():
        print("我们先顶一个小目标,比如赚它一个亿,这是我爸爸{}".format(father))
    return f_hobby

func = songyunjie_family()
func()

obj = func.__closure__[0]
print(obj.cell_contents,"<111>")

三、复杂版本

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)
# 返回的是元组
tup = func() # big_master()
print(tup)   # tup =  (jiejie,meimei)
# 获取姐姐
jiejie = tup[0] # jiejie 函数
# 获取妹妹
meimei = tup[1] # meimei 函数

# big_master 是闭包函数,是直接被mashengping_family返回出来的
# jiejie,meimei 是通过big_master间接被返回到函数外面的
# 调用妹妹
meimei()  # 调用妹妹函数
# 调用姐姐
jiejie()  # 调用姐姐函数

#看它是不是闭包函数,是就可以用
# cell获取单元格对象结果是一个函数名
# 加() 运行
# ### 获取闭包函数使用的变量  __closure__
res = func.__closure__
print(res,"<222>")
#  cell_contents 用来获取单元格对象当中的闭包函数
jiejie = res[0].cell_contents 
meimei = res[1].cell_contents

# 通过获取单元格对象 -> 获取单元格对象中的内容 -> 实际的调用
jiejie()
meimei()

print(jiejie.__closure__[0].cell_contents)
print(meimei.__closure__[0].cell_contents)

四、闭包的特征和意义

1、特征

内函数使用了外函数的局部变量
那么该变量与闭包函数发生绑定
延长该变量的生命周期
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)
"""
10实参 -> val 形参
因为内函数inner是闭包函数,使用了外函数val
那么该变量val生命周期被延长,没有随着函数调用的结束而释放.
func(15) 把15这个参数赋值给num这个形参
res = inner(15)  => return val + num =>10 + 15 => 25

2、意义

引入:

# 模拟鼠标点击次数
num = 0
def click_num():
    global num
    num += 1
    print(num)

click_num()
click_num()
click_num()
num = 100
click_num()
click_num()

2.1 使用闭包函数改写点击次数

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

def click_num():
    num = 0
    def func():
        nonlocal num
        num += 1
        print(num)
    return func
func = click_num()
func()
func()
num = 1000
func()
func()
func()
func()
func()

五、匿名函数

用一句话来表达只有返回值的函数
"""语法:lambda 参数 : 返回值 """
"""追求代码:简洁,高效"""

1、无参的lambda表达式

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

2、有参的lambda 表达式

def func(n):
    return type(n)
    
# 改写    
func = lambda n : type(n)
print(  func([1,2,3])  )

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)

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

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)

 

posted @ 2020-12-02 22:07  Bo7-w  阅读(118)  评论(0编辑  收藏  举报