菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
59
0

day10-Python运维开发基础(函数嵌套、nonlocal声明局部变量、闭包、locals/globals、lambda表达式)

原创
05/13 14:22
阅读数 40304

 

1. 函数的嵌套与nonlocal 声明局部变量

 

 

# ### 函数的嵌套
"""
函数和函数之间可以互相嵌套:
    嵌套在内层的叫做内函数
    乔涛在外层的叫做外函数
"""

def outer():
    
    def inner():
        print("我是inner函数 ... ")
    inner()


# (1)内部函数可以直接在函数外部调用么 不行
# inner() 


# (2)调用外部函数后,内部函数可以在函数外部调用吗 不行
# outer()
# inner()

# (3)内部函数可以在函数内部调用吗 可以
# outer()

# (4)内部函数在函数内部调用时,是否有先后顺序 有的 先定义在调用


# 定义三个函数 outer函数中有inner ,inner函数中有smaller, 调用smaller

def outer():
    
    def inner():
        
        def smaller():
            
            print(id)
            print("我是smaller函数")
        smaller()
    inner()
outer()


#找寻变量的调用顺序采用LEGB原则(即就近原则)
"""
B —— Builtin(Python);Python内置模块的命名空间      (内建作用域)
G —— Global(module); 函数外部所在的命名空间        (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
L —— Local(function);当前函数内的作用域            (局部作用域)
依据就近原则,从下往上 从里向外 依次寻找
"""
函数的嵌套 示例代码
# ### nonlocal 用来修饰局部变量
"""
nonlocal 符合LEGB原则
(1)用来修改当前作用域上一级的局部变量
(2)如果上一级没有,在向上一级依次寻找
(3)如果再也找不到了,直接报错
"""


# (1)用来修改当前作用域上一级的局部变量

def outer():
    a = 13
    def inner():
        nonlocal  a
        a = 15
        print(a)
    inner()
    print(a)
outer()

# (2)如果上一级没有,在向上一级依次寻找
# b = 200
def outer():
    b = 100
    def inner():
        b = 200
        def smaller():
            nonlocal b
            b = 101
            print(b)
        
        smaller()
        print(b)
    inner()
    print(b)
outer()

# (3)如果再也找不到了,直接报错
"""
b =200
def outer():

    def inner():

        def smaller():
            # nonlocal 只修改局部变量
            nonlocal b
            b +=10
        
        smaller()
        print(b)

    inner()

outer()
"""
# (4)不通过nonlocal , 是否可以修改局部变量
def outer():
    lst = [1,2,3]
    def inner():
        lst[-1] += 10
    inner()
    print(lst)
outer()
        
nonlocal 示例代码

 

2. 闭包函数

 

 

# ### 闭包函数
"""
生命周期从长到短:
    内置空间变量 -> 全局空间变量 -> 局部空间变量
    内置空间变量 : 在解释器退出之后,就会释放空间
    全局空间变量 : 在文件执行结束之后,就会释放空间
    局部空间变量 : 在调用完函数之后,就会释放空间

定义: 内函数使用了外函数的局部变量,外函数把内函数返回出来的过程,叫做闭包,这个内函数叫做闭包函数
"""

# (1) 基本语法
def zouyongling_family():
    father = "王健林"
    def hobby():
        print("先定一个小目标,比如挣他一个亿,这是我爸爸%s说的" % (father))
    return hobby
    
func = zouyongling_family() # func = hobby
func()

# 获取闭包函数使用的变量  __closure__ , cell_contents(了解)
# __closure__ 获取单元格对象,这个对象中含有延长生命周期的变量值
tup = func.__closure__
print(tup)    # (<cell at 0x00000226506595E8: str object at 0x00000226506EC450>,)
print(tup[0]) # <cell at 0x00000226506595E8: str object at 0x00000226506EC450>
# cell_contents 这个属性 可以获取单元格对象中的值,如果有证明是一个闭包,如果没有,就不是一个闭包
print(tup[0].cell_contents)

# (2) 升级闭包函数
"""
特点:内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的生命周期
"""
def huanglexi_family():
    jiejie = "马蓉"
    meimei = "马诺"
    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 = huanglexi_family()# func = big_master
print(func)
tup = func() # big_master()  => tup = (jiejie_hobby,meimei_hobby)
print(tup) # (<function huanglexi_family.<locals>.jiejie_hobby at 0x000001425AE73BF8>, <function huanglexi_family.<locals>.meimei_hobby at 0x000001425AE7C158>)
# 获取闭包函数
jiejie_hobby = tup[0]
meimei_hobby = tup[1]
# 调用函数
jiejie_hobby()
meimei_hobby()
闭包函数 示例代码
# ### 闭包的特点:
"""
内函数使用了外函数的局部变量,该变量与内函数发生绑定,延长该变量的生命周期
"""
def outer(val):
    def inner(num):
        return val + num
    return inner
func = outer(10) # func = inner
res = func(5) #  val + num = 15
print(res)

"""
代码解析:
    outer(10) val = 10
    func = inner
    func(5)  num = 5
    return val + num => return 10 + 5 => 15
    print(res) => 15
"""

# ### 闭包的意义
"""
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
"""
# 记录鼠标点击次数操作
# 方法一 : 全局变量的作用范围太大,容易被串改
total = 0
def click():
    global total
    total += 1
    print(total)
click() # 1
click() # 2
click() # 3
click() # 4
total = 100
click()

# 方法二 :
def myclick():
    x = 0
    def click():
        nonlocal x
        x += 1
        print(x)
    return click
func = myclick()
print(func)
func() # 1
func() # 2
func() # 3
func() # 4
x = 100
func()
闭包的特点 示例代码

 

 3. locals 与 globals、lambda表达式(匿名函数)

 

 

 

# ### locals 和 globals
"""
-- globals() :返回字典,存放着全局作用域所有内容
-- locals()  :返回字典,当前作用域所有内容
"""

# (1)locals
"""
在函数外,获取locals打印之前所有变量内容,形成字典,获取全局作用域的内容
在函数内,获取locals调用之前所有变量内容,形成字典,获取局部作用域的内容
"""
# 在函数外
"""
a = 1
b = 2
res = locals()
c = 3
print(res)
"""
# 在函数内
"""
def func():
    a = 1
    b = 2
    res = locals()
    c = 3
    print(res)
func()
"""
# (2)globals
"""
在函数外,获取globals打印之前所有变量内容,形成字典,获取全局作用域的内容
在函数内,获取globals调用之前所有变量内容,形成字典,获取全局作用域的内容
"""
# 在函数外
"""
a = 1
b = 2
res = globals()
c = 3
print(res)
"""
a1 = 1
b1 = 2
# 在函数内
def func():
    a = 1
    b = 2
    res = globals()
    c = 3
    print(res)
c1 = 3
func()
d1 = 4

# globals 可以动态的创建变量
# 声明变量
wangwen = "真靓"

# globals 创建一个全局变量 : 返回的是全局字典,通过在字典中添加键值对,来动态创建变量,键就是变量名,键所对应的值也是这个变量的值
"""
dic = globals()
print(dic)
dic["yangmazi"] = "真聪明"
print(yangmazi)
"""

# globals 创建多个全局变量
"""动态创建p1~p5 5个变量"""
def func():
    dic = globals()
    print(dic)
    for i in range(1,6):
        dic[ "p%d" % (i) ] = i
func()
"""
"p%d" % (1) => "p1"
"p%d" % (2) => "p2"
"p%d" % (3) => "p3"
"p%d" % (4) => "p4"
"p%d" % (5) => "p5"
"""
print(p1,p2,p3,p4,p5)
locals和globals 示例代码
# ### 匿名函数 : lambda表达式
"""
用一句话来表达只有返回值的函数
特点: 简洁 , 高效
语法:
    lambda 参数 : 返回值
"""

# (1)没有参数的lambda 表达式
def func():
    return "我是func函数 ... "

# 改写
func = lambda : "我是func函数 ... "
res = func()
print(res)

# (2)有参数的lambda 表达式
def func(n):
    return type(n)

# 改写
func = lambda n : type(n)
res = func(4.56)
print(res)

# (3)带有判断条件的lambda 表达式
def func(n):
    if n % 2 == 0:
        return "偶数"
    else:
        return "奇数"
res = func(3)
print(res)

# 三目运算符
"""
真区间值 if 条件表达式 else 假区间值
如果条件表达式满足,
    就返回真区间值
    否则,就返回假区间值
"""
def func(n):
    return  "偶数" if n % 2 == 0 else "奇数"

res = func(3)
print(res)

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

# 比较两个数的大小,返回最大值
def func(x,y):
    if x>y:
        return x
    else:
        return y

# lambda 改写
func = lambda x,y : x if x>y else y
res = func(3,2)
print(res)
lambda表达式 示例代码

 

 

day10

发表评论

0/200
59 点赞
0 评论
收藏