zoukankan      html  css  js  c++  java
  • 函数的命名空间和作用域

    一、函数的命名空间

    命名空间:name space是从名称(name)到对象(object)上的映射。

    当一个name映射到一个object上时,这个name和这个object就有了绑定(bind)关系,或者说这个name指向了这个object。

    每个name只对应一个object,而一个object可有多个名字。这就是类与实例的关系。

    不同的命名空间在不同的时刻被创建,并且有不同的生命周期。

    内置的命名空间在python解释器启动的时候创建的,并且一直保留,不会删除。

    在python程序中的任何地方,都存在着命名空间。

    python中有三种命名空间:

    局部命名空间:函数内的名称空间就是局部的。

    全局命名空间:写在函数外面的变量名。模块内的命名空间就是全局的。

    内置命名空间:python解释器启动时创建的,包括异常内型、内建函数和特殊方法,可以在代码中的任何地方调用。

    函数外面的变量可以在函数里面调用,函数里面的变量不能在外边用,因为有独自的作用域。

    注意循环体内不会创建作用域。 

    名称空间的加载顺序:

    a.python解释器首先运行起来,加载所有内置命名空间中的名字。

    b.然后按照顺序加载全局命名空间

    c.局部命名空间随函数的调用而创建,随着函数的结束而消除。

    命名空间的查找顺序:

    a.如果在函数内调用一个变量,先在函数内(局部命名空间)查找,如果没有找到则去函数外部(全局命名空间)查找,如果还是没有找到,则去内置命名空间中查找,内置空间再找不到那就只有报错。

    b.如果在函数外调用一个一个变量,先查全局命名空间,也就是本地,如果没有找到,那就去内置命名空间中查找,这里找不着也没辙。

    二、函数的作用域

    作用域:一个名字可以使用的区域范围。

    全局作用域:内置名字空间和全局名字空间中的名字都属于全局作用域
    局部作用域:局部名字空间中的名字属于局部作用域。
    局部作用域可以使用全局作用域中的变量
    而全局作用域不能使用局部作用域中的变量
    局部作用域中的变量又可以被更小的作用域所调用
    作用域链:小范围作用域可以使用大范围的变量,但作用域链是单向的,不能反向。

    globals():保存了在全局域中的名字和值,无论在哪打印值都一样
    locals():保存了当前作用域中变量,根据执行的位置来决定作用域中的内容
    如果在全局执行,globals()和locals()的结果是相同的

    global :声明参数是全局变量

    nonlocal :调用最近的这个参数

    用几个例子来演示:

    (1)代码的加载顺序

    #代码执行的顺序
    def func2():                             #1  读取函数
        print('my name is func2')             #5
        print('多写一行')                             #6   
        if True:                                          #7
            print('又多写了一行')                      #8
        return 'func2的返回值'                        #9
    
    def func():                              #2
        ret = func2()                            #4   调用函数
        print(ret)                                            #10
        n = 20                                                  #11
        print(n)                                                   #12   
    
    func()                                     #3  执行函数

    (2)函数的镶嵌

    def func():
        def kebi():
            print('我是科比.布莱恩特')
        kebi()    #要想调用kebi,必须先要再func()里面调用
    
    func()

    (3)作用域

    n = 1
    def func():
        print(n)      #会报错,在圈子里不能改变圈子外的值
        n = n+1
    
    func()
    #理解下面
    n = 100
    def func():
    n = 200
    print(n)
    func()
    #上面代码不会报错,本质原因是有2个n,局部作用域与全局作用域各一个

    n = 1
    def func():
        global n    #用global来声明这是一个全局变量
        n = n+1
        print(n)
    
    func()
    
    结果:
    2

    如果想调用局部中的变量

    n = 0
    def func1():
        n = 1
        def func2():
            nonlocal n  #调用就近的一个局部变量,不会调用全局变量
            n +=1
        func2()
        print(n)
    func1()
    print(n)
    
    结果:
    2
    0

    三、函数的名字

    函数名可以赋值

    def foo(sr):
        print(sr*2)
    bar = foo
    bar(123)
    
    结果:
    246

    可以作为一个数据结构的元素

    def foo(sr):
        print(sr*2)
    lst = [1,2,foo,5]
    print(lst)
    
    结果:
    [1, 2, <function foo at 0x000002DD65CE4048>, 5]
    
     <function foo at 0x000002DD65CE4048> foo的内存地址

    函数可以作为一个函数的参数

    def foo(sr):
        print(sr*2)
    def bar(lst):
        return lst
    print(bar(foo))
    
    结果:
    <function foo at 0x000002AE437C4048>


    函数的名字可以作为一个函数的返回值

    def foo(sr):
        print(sr*2)
    def bar():
        return foo
    print(bar())
    
    结果:
    <function foo at 0x000001DF93844048>
  • 相关阅读:
    [洛谷P2824][题解][HEOI2016/TJOI2016]排序
    [整理]CSP-S2019第一轮试题解析
    [整理]Luogu CSP2020第一轮模拟赛
    [洛谷P4395][题解][BOI2003]Gem 气垫车
    [洛谷P5322][BJOI2019][题解]排兵布阵
    [整理]U S A C O 代 码 小 合 集
    第02组Alpha冲刺 总结
    第02组 Alpha冲刺 (6/6)
    第02组 Alpha冲刺 (5/6)
    第02组 Alpha冲刺 (4/6)
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/7767579.html
Copyright © 2011-2022 走看看