zoukankan      html  css  js  c++  java
  • pytho-函数作用域

    函数外部可以使用函数内部的变量?

    def test():
        a = 10
        print(a)
    
    
    test()   # 
    print(a)  # NameError: name 'a' is not defined
    

    代码运行的形式

    python解释器开始运行之后,会在内存里面开辟一个空间,每当遇见一个变量的时候,就把变量名和值的对应关系进行记录下来,但是遇见函数的时候,解释器只是象征性的将函数名读到内存中,表示知道这个函数的存在了,至于函数内部的变量和逻辑,解释器根本不关心。
    等到执行调用函数的时候,python解释器会在开辟一块内存空间来存储这个函数里面的内容,这个时候,才关心还是里面的这些变量,而函数中的变量会存储在新开辟的内存空间里面,函数中的变量只能在函数内部进行使用,并且会随着函数执行完毕,这块内存中的所以的内容也会被清空。

    "存放名字和值的关系"的空间起了一个名字,叫作:命名空间。
    代码开始,创建和存储"变量名和值的关系"的空间叫作全局命名空间。
    在函数中运行开辟的临时的空间叫作局部命名空间。

    命名空间和作用域

    命名空间有下面的几种形式:

    • 全局命名空间
    • 局部命名空间
    • 内置命名空间

    内置命名空间

    内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

    三种命名空间之间的加载与取值顺序:
    加载顺序:内置命名空间(程序运行前进行加载)(Rightarrow)全局命名空间(程序运行中:从上到下加载)(Rightarrow)局部命名空间(程序运行中:调用才加载)
    取值顺序:

    • 在局部调用的时候:局部命名空间(Rightarrow)全局命名空间(Rightarrow)内置的命名空间
    • 在全局调用的时候:全局命名空间(Rightarrow)内置命名空间
      在寻找变量时,从小范围去寻找,一层一层到大范围去找寻。

    作用域作用域

    按照生效范围分为:

    • 全局作用域:包括了名称空间和全局名称空间,在整个文件的任意位置都有被引用,全局有效
    • 局部作用域:局域名称空间,只能在局部内生效。

    global和nonlocal关键字

    global:

    • 声明一个全局变量
    • 在局域作用域想要对全局变量进行修改时,则可以使用global关键字(只能是字符串和数字)
    def test():
        global a
        a = 10
        print(a)  # 10
    
    
    test()
    print(a)  # 10
    
    
    count = 1
    def search():
        global count
        count = 2
    search()
    print(count)  # 2
    
    

    nonlocal:

    • 不能修改全局变量。
    • 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改 变。
    def add_b():
        b = 42
    
        def do_global():
            b = 10
            print(b)
    
            def dd_nonlocal():
                nonlocal b
                b = b + 20
                print(b)
    
            dd_nonlocal()
            print(b)
    
        do_global()
        print(b)
    
    
    add_b()
    

    总结:
    1、局部作用域改变全局变量用global, global同时还可以定义新的全局变量

    2、内层函数改变外层函数变量用nonlocal, nonlocal不能定义新的外层函数变量,只能改变已有的外层函数变量

    函数的嵌套和作用域链

    def f1():
        print("1111")
    
        def f2():
            print("2222")
    
            def f3():
                print("3333")
            f3()
        f2()
    f1() # 1111 2222 3333 
    **********************************************************************************
    def f1():
        def f2():
            def f3():
                print("in f3")
            print("in f2")
            f3()
        print("in f1")
        f2()
        
    f1()
    

    def f1():
        def f2():
            def f3():
                print("in f3")
            print("in f2")
            f3()
        print("in f1")
        f2()
    f1()
    

    函数的作用域链

    def f1():
        a = 1
        def f2():
            print(a)
        f2()
    
    f1()  # 1
    
    
    

    函数名的本质

    函数名本质上就是函数的内存地址

    def f1():
        a = 1
        def f2():
            print(a)
        f2()
    
    
    print(f1)  # <function f1 at 0x000001ADCD0D3E18>  # 内存地址
    

    1函数是可以被引用的

    def func():
        print("function")
    
    f = func
    f()  # function
    

    2.可以被当作容器类型的元素

    def func1():
        print("function1")
    
    def func2():
        print("function2")
    
    def func3():
        print("function3")
    
    def func4():
        print("function4")
    
    func_list = [func1, func2, func3, func4]
    
    for i in func_list:
        i()
    '''
    function1
    function2
    function3
    function4
    '''
    
  • 相关阅读:
    《Effective Java》—— 读后总结
    自己写的数据交换工具——从Oracle到Elasticsearch
    Oozie 快速入门
    [大数据之Spark]——快速入门
    《Spark快速大数据分析》—— 第七章 在集群上运行Spark
    [大数据之Sqoop] —— Sqoop初探
    Java程序员的日常——存储过程知识普及
    Java程序员的日常—— 基于类的策略模式、List<?>与List、泛型编译警告、同比和环比
    org.postgresql.util.PSQLException:致命:抱歉,已经有太多客户了(org.postgresql.util.PSQLException: FATAL: sorry, too many clients already)
    PostgreSQL学习笔记(九) 用户、角色、权限管理
  • 原文地址:https://www.cnblogs.com/yangchangjie150330/p/10530299.html
Copyright © 2011-2022 走看看