zoukankan      html  css  js  c++  java
  • 函数2

    命名空间、作用域、取值顺序:

    全局命名空间 、局部命令空间、内置命令空间的关系
    当python解释器,对一个文件从上到下开始执行代码时,在内存中就为文件开个内存空间,在遇到变量 和 函数的定义时,就将 “变量名和值的关系”
    及 “函数名和值的关系”保存在这个内存空间中,这块内存空间---叫做全局命令空间 或者叫做 全局名称空间。当整个py文件执行结束,全局名称空间从内存中释放。
    全局命令空间中,保存在文件中,函数外的变量的名字 和 变量内容对应的内存地址,及 函数名和函数体对应的内存地的映射关系,可以叫做字典。

    python解释器,对py文件,从上向下执行代码时,当遇到函数的调用或叫函数的执行时,会在内存中临时开辟一个内存空间,用来保存函数体内部定义的变量,及子函数映射关系。
    当函数执行完毕,临时空间释放,这个临时空间, 我们称之为局部命令空间或局部名称空间。

    内置命令空间;当py文件运行前,python解释器,加载到内存中,创建一个内存空间,用来存放内置函数input,print,len 及 类 list,tuple ,dict,str等的映射关系,这个内存
    空间,我们称之为内置名称空间。内置命令空间的东本,全局命令空间,可以引用,调用,局部命令空间,也可以调用。同样,当解释器执行完py文件时,也退出,释放出该块内存空间。

    在不同的空间的取值顺序
    在全局空间,即py文件的任意位置,除掉函数内部,引用对象,先在全局空间找,再到内置空间找,找不到就报错。 全局空间找 ----> 内置命令空间找
    在局部空间,即函数内部的任意位置,引用对象,先在局部命名空间找,再到全局命令空间找,最后到内置空间找,找不到则报错。 局部空间找 ---> 全局名称空间找 ---> 内置命名空间找

    作用域:

    按照对象的作用范围,或者叫生命周期,分为全局作用域 ,局部作用域 。
    全局作用域:对于内置名称空间,全局名称空间的对象 ,在整个文件执行过程中一直有效,直到文件执行结束,才结束其生命周期。因此我们说,内置空间、全局空间的对象它的作用范围,或者
    作用域 ,为全局作用域。
    局部作用域 :对于函数而言,当执行时,开辟了局部命名空间,局部命令空间的对象,仅在函数执行过程中,一直有效,函数执行结束 ,其生命周期结束。因此我们说,局部命名空间的对象它的作用
    范围或者叫作用域,为局部作用域。 

    def len(obj):
        print(20)
        return 20
    ret = len('hello world')  # 我们知道python有一个内置函数len(),它是内置空间的,但是我们在全局命令空间调用len时,先到全局空间找,找到,后面有一个括号 ,就执行全局空间定义的len()函数
    print(ret)                            # 相当于去内置空间len()函数进行了覆盖
    
    
    def func8(obj):
        len(obj)                            # 在局部空间时,执行代码时,先在局部空间找函数名,没有找到,再到全局名称空间,找到执行
    func8([1,3,5])           # 控制台打印 20
    
    
    def func9():
        def len():
            print("局部命名空间")
        len()                                    # 当执行func9()函数时,先定义局部空间中的len(),然后调用执行len(),先在局部空间去找,找到就执行
    
    func9()    # 控制台中打印输出 : 局部命名空间
      
    print(len("str"))   # 3    在全局空间没有找到len,再到内置命名空间
    
    def func1(obj):
       return  len(obj)          # 函数执行时,先到局部命名内间找,没有找到再到全局命名空间找,没有找到,最后到内置名称空间找。
    print(func1("sbcde"))  # 5 

     

    在函数中, global  和  nonlocal 关键字的详解:

    # nonlocal 关键字 ,只能用在子函数中,声明引用 上级的变量(直接上级没有,就到上上级,直到最顶端上级函数没有,就报错,先找到先引用
    # nonlocal ---子函数对父函数中的变量的修改,直接父级没有,到上上父级到,不包括全局作用命令空间
    def GrandFather():
            count = 6
            def Father():
                count = 12            # 被下级函数,声明nonlocal count的引用
                def son():
                    nonlocal count   # 子函数中,用nonlocal声明一个变量,它会从它的上级函数去找,找到就引用
                    count = count + 1
                    print(count)
                son()
            Father()
    # 函数调用
    GrandFather()    # 输出结果,打印13
    
    
    def GrandFather():
        count = 6                     # 被下级的 nonlocal count 找到,被引用
    
        def Father():
            # count = 12  # 现在我这一行代码,注释掉了
    
            def son():
                nonlocal count  # 子函数中,用nonlocal声明一个变量,它会从它的上级函数去找,直接上级没有,就到上上级,找到就引用
                count = count + 1
                print(count)
            son()
        Father()
    
    # 函数调用
    GrandFather()
    
    
    #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$####################
    # count = 10
    # def GrandFather():
    #     # count = 6           # 这一行也注释掉
    #
    #     def Father():
    #         # count = 12  # 被下级函数,声明nonlocal count的引用
    #
    #         def son():
    #             nonlocal count  # 子函数中,用nonlocal声明一个变量,它会从它的上级函数去找,找到就引用,但是不引用全局命令空间,
    #                             # 在所有上级,上上级....函数中都找不到,则报错:SyntaxError: no binding for nonlocal 'count' found
    #             count = count + 1
    #             print(count)
    #         son()
    #     Father()
    #
    # GrandFather()
    
    # 子函数中的 nonlocal variable 引用自哪一层,那层及以下层全部发生改变
    
    # global关键字 用在函数中,用于声明一个变量是全局命名空间的变量,如果在全局空间,没有找到,则创建,否则直接引用
    
    # 第一种情况:函数中通过 global variable 声明的全局变量,在全局命令空间已经定义,直接引用
    globalv = "I am a global variable"
    def func():
        global globalv
        print(globalv)
    func()    # 输出,打印: I am a global variable
    
    
    # 第二种情况:函数中通过 global variable 声明的变量,在全局命名空间没见有定义,那么在执行函数体过程中,会在全局名称空间
    # 创建此变量,并用作用域,为全局作用域,即生命周期为整个文件
    # def func2():
    #     global global_test
    #     global_test = "I am from function"
    #     print(global_test)
    # func2()     # 屏幕打印:I am from function
    # print(global_test) # I am from function
    
    
    # 第三种情况:在函数中,声明了global variable ,但未调用过此函数,那么,这时在全局空间引用此变量,会报错
    def func2():
        global global_test
        global_test = "I am from function"
        print(global_test)
    # func2()     # 把这一行代码注释掉,即虽然定义了函数,但是不调用,没有调用 ,就不会执行global global_test 语句,就不会在全局命令空间,创建变量
    print(global_test) # 所以,在全局命名空间,调用变量时,报错: NameError: name 'global_test' is not defined  名称错误

     对于global 和 nonlocal 关键字补充:

    # 7题:
    # 7.1
    # a = 2
    # def wrapper():
    #     print(a)
    # wrapper()
    # 答:在局部空间,可以引用 全局命名空间的对象,所以此代码成立。
    
    # # 7.2
    # a = 2
    # def wrapper():
    #     a += 1
    # print(a)
    # wrapper()
    
    # 答: 此代码不成立,在局部名称空间,不能修改全局变量,需要声明为使用全局变量
    # 解决办法:
    # def wrapper():
    #     global a
    #     a += 1
    # print(a)
    # wrapper()
    # print(a)
    
    # 7.3 题:
    def wrapper():
        a = 1
        def inner():
            print(a)
        inner()
    wrapper()
    
    # 答 : 可以上级函数的命令空间的变量对下级函数而言,是可见的,可以直接引用
    # 7.4 题:
    def wrapper():
        a = 1
        def inner():
            a += 1
            print(a)
        inner()
    wrapper()
    # 答 :代码不成立,下级函数引用上级函数里的变量,并修改,不成立,要修改的话,用nonlocal关键字声明。

    最后总结: 在函数里可以直接引用 全局名称空间的 变量,但要在函数里--修改--全局名称空间的变量,则在函数里用global关键字声明 变量;
    下级函数,可以直接引用上级函数里的变量,但下级函数要对上级函数(包括上上级....)的变量修改,则在函数内要用nonlocal关键字声明该变量

     globals() 和 locals()函数:

    #globals() 与 locals()函数:
    # glocals()函数 :返回执行这条命令的,当前作用域的全局变量的一个字典
    # locals() : 返回执行这条命令时,当前作用域的局部变量的一个字典
    
    # 当在文件中,函数外执行 时, 当前作用域 就是全局变量 所处的 全局命名空间,因此 globals() 与 locals() 结果 一样
    print(globals())
    print(locals())
    def test():
        a = 2
        b = 3
        print(globals())
        print(locals())    #  {'b': 3, 'a': 2}
    test()
    
    def test1():
        a = 2
        b = 3
        def inner():
            c = 5
            d = 6
            print(globals())  # 全局的不变
            print(locals())  #  {'d': 6, 'c': 5}
        inner()
    test1()

    函数名可以作为容器类数据类型的元素,常用应用场景:

    def register():
    print("正在注册")
    pass
    def login():
    print("正在登陆")
    pass
    def purchase():
    print("购买功能正在开发中.....")
    pass
    def escape():
    print("你已成功逃逸.....")
    exit()
    pass

    function_dic = {1:register,2:login,3:purchase,4:escape}
    while 1:

    choice_num = input('''
    1 .................. 注册
    2 .................. 登陆
    3 .................. 购买
    4 .................. 退出
    请输入【1-4】:
    ''')
    if choice_num.isnumeric():
    if int(choice_num) in list(range(1,5)):
    function_dic[int(choice_num)]()



  • 相关阅读:
    《Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks》
    YOLO(v1)
    循环赛日程表问题(分治法)
    平面最接近点对问题(分治法)
    SQLite学习心得
    如何找到Linux下常用命令的源码
    WiFi安全之WPA介绍
    七种不良的工作习惯
    Git 技巧小结
    微信智能硬件平台 简介
  • 原文地址:https://www.cnblogs.com/chris-jia/p/9486887.html
Copyright © 2011-2022 走看看