• locals和globals,函数的嵌套,nonlocal,闭包函数及特点以及匿名函数---day11


    1.locals和globals

    1.1locals  获取当前作用域中的所有内容

    locals 如果在函数外,调用locals(),获取打印的是打印之前的所有变量,返回字典,全局空间作用域
    locals 如果在函数内,调用locals(),获取的是调用之前的所有变量,返回字典,局部空间作用域
    
    #例子1
    
    a = 1
    b = 2
    res = locals()
    c = 3 
    print(res)  #打印前面所有的变量的值,返回一个字典
    d = 4  #不打印
    
    a = 1
    def outer():
        def inner():
            return 'www'
        inner()
    res = locals()
    b = 2
    c = 4
    print(res) #打印前面所有全局变量,返回一个字典
    d = 5  #不打印
    
    #例子2
    a = 1
    def func():
        b = 2     #这个是调用之前的局部变量
        res =locals()  #这个是调用
        c = 3
        print(res)#打印的是调用之前的局部内的变量是b = 2,返回字典形式{'b':2},
        d = 4
    func()
    
    
    a = 1
    def outer():
        b = 2  #不会打印外函数的局部变量b=2
        def inner():
            c = 4  #内函数的局部变量
            e = 6  #内函数的局部变量
            res = locals() 调用
            d =4
            print(res) # 打印内函数的局部变量返回{'c':4,'e':6}
        inner()
    outer()
    

      

    1.2globals 获取全局作用域的所有内容

    globals 如果在函数外,调用globals(),获取打印的是打印之前的所有全局变量,返回字典,全局空间作用域
    globals 如果在函数内,调用globals(),获取打印的是调用之前的所有全局变量,返回字典,全局空间作用域
    
    #例子3
    a = 5
    b = 6
    res = globals()
    c = 7
    print(res) #打印之前的所有变量 返回字典形式
    d = 8 #不打印 该变量在打印之后
    
    a = 1
    def outer():
        def inner():
            return 'www'
        inner()
    res = globals()
    b = 2
    c = 4
    print(res) #打印前面所有全局变量,返回一个字典
    d = 5  #不打印
    
     #例子4
     a = 10  #全局变量
     def func():
        b = 11
        c =12
        res = globals()  #调用
        d = 13
        print(res)#打印出的是调用之前的所有全局变量{'a':10,'ff':33}
    ff = 33  #全局变量
    func()   #执行函数
    zz = 50  #不打印,因为这是在整个func函数全部执行完才定义的全局全局变量
    

      

    1.3globals返回的是系统的字典

    #1.正常方式定义变量
    zhangsan = '112233'
    
    
    #2.通过系统的全局字典添加键值对,可以动态创建全局变量
    dic =globals()
    print(dic) ##{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001DEA2B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/pythonproject/python_all/ceshi/day_01.py', '__cached__': None, 'dic': {...}}
    
    
    # 传递字符串 ,创建一个变量
     k = 'liuwei'
     dic[k] = '刘伟'  #键值对添加'liuwei':'刘伟'
     print(liuwei)  #通过键取值
    
    
    #3.批量创建全局变量 在函数中
    def func():
        dic = globals()
        for i in range(1,6):
            dic['p%d'%(i)] = i  #p1 p2 p3 p4 p5 p6
    func()
    print(p1)  #1
    print(p2)  #2
    print(p3)  #3
    print(p4)  #4
    print(p5)  #5
    

      

    2.函数的嵌套

    函数的嵌套:
        嵌套在函数的外边叫作外函数
        嵌套在函数的里面叫作内函数
    def outer():
        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); 当前函数内的作用域    (局部作用域) 
    依据就近原则,从下往上 从里向外,依次寻找
    '''
    

      

    3.nonlocal

    nonlocal 关键字 用来更改局部变量
    nonlocal  遵循LEGB原则
    (1)nonlocal  专门用来修改当前作用域上一级的局部变量
    (2)如果上一级找不到,那么就继续向上寻找
    (3)全部找不到,直接报错 (不涉及全局变量)
    
    #(1) nonlocal 专门用来修改当前作用域上一级的局部变量
    def outer():
        a = 10
        def inner():
            nonlocal a
            a = 20
        inner()
        print(a)  #a = 20
    outer()
    
    #(2) 如果上一级找不到,那么久继续向上寻找
    '''nonlocal 只能修改局部变量'''
    def outer():
        a = 41
        def inner():
            def smaller():
                nonlocal a
                a = 42
                print(a)
            smaller()
            print(a)  #42
        inner()
        print(a) #42
    outer()
    
    #(3) 全部找不到,直接报错
    a = 41
    def outer():
        def inner():
            def smaller():
                nonlocal a  #找不到局部变量a  报错
                print(a)
            smaller()
            print(a)
        inner()
        print(a)
    outer()
    
    
    #(4) 不使用nonlocal 是否可以修改局部变量呢?
    def outer():
        lst = [1,2,3]
        def inner():
            lst[-1] = 52
        inner()
        print(lst)
    outer()
    
    #当局部中有可变数据类型时,可以不使用nonlocal来修改全局变量
    def outer():
        dic = {'a'1,'b':2}
        def inner():
            dic['a'] = 5
        inner()
        print(dicvar)
    outer()
    
    
    #注意点  两者之间的区别
    #第一种  这种是在函数内修改局部变量
    def outer():
        a = 10
        def inner():
            nonlocal a
            a = 2
            print(a)  #a = 2
        inner()
        print(a)  # a = 2
    outer()
    #第二种  这种是在函数内自己又定义了一个变量a,与外函数的局部变量不是同一个
    def outer():
        a = 10
        def inner():
            a = 2
            print(a)  # a = 2
        inner()
        print(a)  # a = 10
    outer()
    

      

    4.闭包函数

    闭包函数:
    闭包函数:
        内函数使用了外函数的局部变量
        外函数将内函数返回出来的过程 叫作闭包
        里面的内函数叫作闭包函数
    #(1) 闭包函数用法
    def wz_family():
        father = '马云'
        def mayun_hobby():
            print('{0}不在乎钱'.format{father})
        return mayun_hobby
    # res = mayun_hobby  <====> res() = mayun_hobby() 
    res = wz_family()
    print(res)  #打印出来的是一个函数内存地址
    res()  #加括号相当于调用函数
    解析:
    wz_family调用函数拿一个变量res接收,返回mayun_hobby,res = mayun_hobby,
    内部函数mayun_hobby需要mayun_hobby加()执行,就可以用res()执行内部函数
    
    #(2) 升级
    def liuwei_familt():
        father = '刘德华'
        jiejie = '刘亦菲'
        meimei = '杨颖'
        money = 1000
        
        def jiejie_hobby():
            nonlocal money
            money  -= 600
            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 = liuwei_familt()  #返回的big_master
    print(func)
    res = func() #相当于调用了big_master()
    print(res)  #返回回来的是[jiejie_hobby,meimei_hobby]
        
    #分别获取姐姐,妹妹这两个函数
    jiejie = res[0]
    jiejie() #相当于调用jiejie_hobby函数
    meimei =res[1]
    meimei()#相当于调用meimei_hobby函数
    
        
    # ### 获取闭包函数使用的变量 __closure__,cell_contents(了解)
    tup = func.__closure__
    print(tup)
    #(<cell at 0x0000000001E15618: function object at 0x0000000001E99AE8>,
    # <cell at 0x0000000001E15678: function object at 0x0000000001E99B70>)
    
    #cell_contents  #功能获取单元对象里面的内容
    jiejie = tup[0].cell_contents
    meimei = tup[1].cell_contents
    print(jiejie)
    #<function weifuqiang_family.<locals>.jiejie_hobby at 0x0000000001E99AE8>
    jiejie()
    meimei()
    

      

    5.闭包特点

    闭包特点:
      内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的生命周期
    #函数的定义处
    def outer(var):  #var = 5
        def inner(num):
            return num+var #num = 4
        return inner
        
    # 函数的调用处
    func = outer(5)
    res = func(4) # ==> inner()
    print(res)
    解析:
    1.实参5 和形参var一一对应  进行接收val = 5
    因为内函数inner 和 val进行绑定,延长了val变量的生命周期,不释放
    func = outer(5)  <====> func = inner
    2,实参4  和形参num一一对应 进行接收num= 4
    return num + val <===> 4+5 = 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_num为全局变量并修改,所以在函数外部也可以修改这个全局变量
    click_func()  #101
    
    #方法二
    def outer():
        click_num = 0
        def inner():
            nonlocal click_num  #定义click_num是一个局部变量,在函数局部内有这个变量
            click_num +=1
            print(click_num)
        return inner
    #click_func = inner
    click_func = outer()
    click_func()  #1
    click_func()  #2
    click_func()  #3
    click_num = 100  #在函数外部不能修改局部内变量
    click_func()  #4
    解析:
    闭包函数:
    首先外函数的局部变量click_num为0,内函数想修改外函数的局部变量就需要用nonlocal声明
    然后才能修改
    click_num = 100在函数外部不能修改函数内部的局部变量
    

      

    6.匿名函数

    匿名函数 lambda 表达式
    用一句话来表达只有返回值的函数  特点:简洁,高效,方便
    语法结构:
        lanbda 参数:返回值
    
    #(1)  无参的lambda表达式
    def func():
        return '我是大哥'
    
    #改成lambda表达式
    func = lambda : '我是大哥'
    res  =  func()
    print(res)
    
    #(2) 有残的lambda 表达式
    def func(n):
        return type(n)
        
    #用lambda表达式
    func = lambda n : type(n)
    res =func()
    print(res)
    
    #(3) 带有判断条件的lambda表达式
    def func(n):
        if n%2 == 0:
            return '偶数'
        else:
            return '奇数'
    
    三元(三目)运算符
    真值 if 条件表达式 else 假值
    如果条件表达式成立 为真 返回真值
    如果条件表达式不成立 为假 返回假值
    
    n = 20
    res '偶数' if n%2 == 0 else '奇数'
    print(res)
    
    #lambda表达式
    func = lambda n : '偶数' if n %2==0 else '奇数'
    res = func()
    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(22,5)
    print(res)
    

      

    总结:今天主要讲了以下个点,locals和globals的用法,函数的嵌套,nonlocal,闭包函数及其特点以及匿名函数

    locals:获取当前作用域中的所有内容

    locals 如果在函数外,调用locals(),获取的是打印之前的所有变量,返回字典,全局空间作用域

    locals 如果在函数内,调用locals(),获取的是调用之前的所有变量,返回字典,局部空间作用域

    globals  获取全局作用域的所有内容

    globals 如果在函数外,调用globals(),获取的是打印之前的所有全局变量,返回字典,全局空间作用域

    globals 如果在函数内,调用globals(),获取的是调用之前的所有全局变量,返回字典,全局空间作用域

    用globals可以通过系统的全局字典添加键值对,可以动态创建全局变量,也可以批量创建全局变量

    函数的嵌套:

    嵌套在函数的外边叫作外函数

    嵌套在函数的里面叫作内函数

    内部函数不可以直接在函数外部调用

    调用外部函数后,内部函数不可以在函数外部调用

    内部函数可以在函数内部调用

    内部函数在函数内部调用时,有先后顺序(必须先定义再调用)

    还讲了LEGB原则就是就近变量的原则,从下往上,从里向外

    nonlocal 通用遵循LEGB原则:

    专门用来修改当前作用域上一级的局部变量

    如果上一级找不到,那么就继续向上寻找

    全部找不到,直接报错 (不涉及全局变量)

    不使用nonlocal可以修改局部变量,当外函数的局部变量是可变数据类型时,内函数可以不用nonlocal来修改局部变量

    闭包函数:

    内函数使用了外函数的局部变量

    外函数将内函数返回出来的过程 叫作闭包

    里面的内函数叫作闭包函数

    还讲了两个获取闭包函数的函数,__closure__,cell_contents

    闭包的特点:

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

    闭包可以优先使用外函数的局部变量
    局部变量在函数外部不能被直接使用
    对局部变量实现了保护的作用,外部无法访问

    匿名函数:用一句话来表达只有返回值的函数  特点:简洁,高效,方便

    语法结构:
    lanbda 参数:返回值

    三元运算符:

    真值 if 条件表达式 else 假值
    如果条件表达式成立 为真 返回真值
    如果条件表达式不成立 为假 返回假值

  • 相关阅读:
    12月上旬的一些记录
    11月底的记录
    备考 19号
    在android 中开发java.net.SocketException: socket failed: EACCES (Permission denied) 报错
    使用JAVA NIO实现的UDP client和server
    ANSI X9.8标准 PIN xor PAN获取PIN BlOCK
    直接拿来用!最火的iOS开源项目(一)
    Anroid ListView分组和悬浮Header实现
    Android 联网监控抓包工具的制作(tcpdump的使用)
    Android tcpdump抓包应用实现
  • 原文地址:https://www.cnblogs.com/weiweivip666/p/12886126.html
Copyright © 2020-2023  润新知