zoukankan      html  css  js  c++  java
  • 函数(命名空间,作用域,嵌套)

    在这里我们首先回忆一下python代码运行的时候遇到函数是怎么做的。

    从python解释器开始执行之后,就在内存中开辟了一个空间

    每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。

    但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。

    等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

    我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间

    代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间

    命名空间一共分为三种:

    #局部命名空间:每一个函数都拥有自己的命名空间


    #全局命名空间:写在函数外面的变量名


    #内置命名空间:python解释器启动之后就可以使用的名字

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

    三种命名空间之间的加载与取值顺序:

    加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

    def func2():
        print('in func2 now')
        print('多写的一行')
        if True:
            print('又多写了一行')
        return 'func2的返回值'
    
    func2()
    
    输出:
    in func2 now
    多写的一行
    又多写了一行
    def func2():
        print('in func2 now')
        print('多写的一行')
        if True:
            print('又多写了一行')
        return 'func2的返回值'
    
    def func():
        ret=func2()
        print(ret)
        n = 20
        print(n)
    
    func()
    
    输出:
    in func2 now
    多写的一行
    又多写了一行
    func2的返回值
    20

    作用域

    作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

    全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

    局部作用域:局部名称空间,只能在局部范围生效

    #作用域:一个名字可以使用的区域
    #全局作用域:内置名字空间和全局名字空间中的名字都属于全局作用域
    #局部作用域:局部名字空间中的名字属于局部作用域
    #局部作用域可以使用全局作用域中的变量
    #而全局作用域不能使用局部作用域中的变量
    #局部作用域中还可以嵌套更小的局部作用域
    #作用域链:小范围作用域可以使用大范围的变量,但作用域链是单向的,不能反向应用

    n = 0
    def func1():
        n = 1
        def func2():
            n = 2
            def func3():
                n = 3
                print(n)
            func3()
        func2()
    
    func1()
    
    输出:
    3


    globals和locals方法

    globals()     #保存了在全局作用域中的名字和值
    locals()       #中的内容会根据执行的位置来决定作用域中的内容
    如果在全局执行
    globals和locals打印的结果是一致的

    n = 1
    def func():
        global n
        n = n+1
    
    func()
    print(n)
    
    输出:
    2

    #函数的嵌套调用和函数的嵌套定义
    #命名空间:三种:内置 全局 局部
    #作用域:两张:全局 局部
    #作用域链:名字的使用 是从小范围到大范围的就近事件
    #globals和locals方法
    #小范围可以使用大范围的,但不能修改
        #如果想要修改全局的:使用global关键字  —— 尽量避免
        #如果想要修改最近拥有该变量的外层函数的:使用nonlocal   ——不影响全局

    n = 0
    def func():
        n = 1
        def func2():
            #n = 2
            def func3():
                nonlocal n
                n+=1
            func3()
            print(n)
        func2()
        print(n)
    
    func()
    print(n)
    
    输出:
    2
    2
    0
    n = 0
    def func():
        n = 1
        def func2():
            n = 2
            def func3():
                nonlocal n
                n+=1
            func3()
            print(n)
        func2()
        print(n)
    
    func()
    print(n)
    
    输出:
    3
    1
    0

    函数的嵌套调用和作用域链:

    def max2(x,y):
        m  = x if x>y else y
        return m
    
    def max4(a,b,c,d):
        res1 = max2(a,b)
        res2 = max2(res1,c)
        res3 = max2(res2,d)
        return res3
    
    print(max4(23,-7,31,11))
    
    输出:
    31

    nonlocal关键字

    1.外部必须有这个变量 
    2.在内部函数声明nonlocal变量之前不能再出现同名变量
    3.内部修改这个变量如果想在外部有这个变量的第一层函数中生效
    def f1():
        a = 1
        def f2():
            nonlocal a
            a = 2
        f2()
        print('a in f1 : ',a)
    
    f1()
    
    输出:
    a in f1 :  2
    
    

    小结

    命名空间:

      一共有三种命名空间从大范围到小范围的顺序:内置命名空间、全局命名空间、局部命名空间

    作用域(包括函数的作用域链):

    小范围的可以用大范围的
    但是大范围的不能用小范围的
    在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
    如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
    如果都没有,报错

    函数的嵌套:

      嵌套调用

      嵌套定义:定义在内部的函数无法直接在全局被调用

    函数名的本质:

      就是一个变量,保存了函数所在的内存地址

















  • 相关阅读:
    PHP网络编程
    traits的使用
    在Apache中使用mod_rewrite模块重写URL
    Lamp下安全配置随笔
    微信开发准备工作
    SQL SERVER技术内幕之7 透视与逆透视
    MVP开发模式的理解
    SQL SERVER技术内幕之5 表表达式
    SQL SERVER技术内幕之4 子查询
    SQL Server Management Studio
  • 原文地址:https://www.cnblogs.com/biluo/p/7788533.html
Copyright © 2011-2022 走看看