zoukankan      html  css  js  c++  java
  • 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 假值
    如果条件表达式成立 为真 返回真值
    如果条件表达式不成立 为假 返回假值

  • 相关阅读:
    std thread
    windows更新包发布地址
    How to set up logging level for Spark application in IntelliJ IDEA?
    spark 错误 How to set heap size in spark within the Eclipse environment?
    hadoop 常用命令
    windows 安装hadoop 3.2.1
    windows JAVA_HOME 路径有空格,执行软连接
    day01MyBatisPlus条件构造器(04)
    day01MyBatisPlus的CRUD 接口(03)
    day01MyBatisPlus入门(02)
  • 原文地址:https://www.cnblogs.com/weiweivip666/p/12886126.html
Copyright © 2011-2022 走看看