zoukankan      html  css  js  c++  java
  • python-函数(命名空间、作用域、闭包)

    一、命名空间

      全局命名空间

      局部命名空间

      内置命名空间

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

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

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

    取值:

      在局部调用:局部命名空间->全局命名空间->内置命名空间

    #在局部使用变量取值情况
    x = 1
    def f(x):
        print(x)
    
    print(10)

    在全局调用:全局命名空间->内置命名空间

    #在全局引用变量x
    x = 1
    def f(x):
        print(x)
    
    f(10)
    print(x)
    #在全局引用内置max
    print(max)

    变量作用域

    Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

    变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4中,分别是:

    • L (Local) 局部作用域
    • E (Enclosing) 闭包函数外的函数中
    • G (Global) 全局作用域
    • B (Built-in) 内建作用域

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

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

    以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

    x = int(2.9)  # 内建作用域
     
    g_count = 0  # 全局作用域
    def outer():
        o_count = 1  # 闭包函数外的函数中
        def inner():
            i_count = 2  # 局部作用域 

    全局变量和局部变量

    定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

    局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:

    #!/usr/bin/python3
    
    total = 0; # 这是一个全局变量
    # 可写函数说明
    def sum( arg1, arg2 ):
        #返回2个参数的和."
        total = arg1 + arg2; # total在这里是局部变量.
        print ("函数内是局部变量 : ", total)
        return total;
    
    #调用sum函数
    sum( 10, 20 );
    print ("函数外是全局变量 : ", total)

    以上实例输出结果:

    函数内是局部变量 :  30
    函数外是全局变量 :  0

    globals() 函数会以字典类型返回当前位置的全部全局变量。

    #在全局调用globals和locals
    print(globals())
    print(locals())
    >>>a='runoob'
    >>> print(globals()) # globals 函数返回一个全局变量的字典,包括所有导入的变量。
    {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'a': 'runoob', '__package__': None}

    locals() 函数会以字典类型返回当前位置的全部局部变量。

    >>>def runoob(arg):    # 两个局部变量:arg、z
    ...     z = 1
    ...     print locals()
    ... 
    >>> runoob(4)
    {'z': 1, 'arg': 4}      # 返回一个名字/值对的字典
    >>>
    #在局部调用globals和locals
    def func():
        a = 12
        b = 20
        print(locals())
        print(globals())
    
    func()

    global关键字

    当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字。

    以下实例修改全局变量 num:

    #!/usr/bin/python3
    
    num = 1
    def fun1():
        global num  # 需要使用 global 关键字声明
        print(num) 
        num = 123
        print(num)
    fun1()
    #以上实例输出结果:
    1
    123

    如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:

    #!/usr/bin/python3
     
    def outer():
        num = 10
        def inner():
            nonlocal num   # nonlocal关键字声明
            num = 100
            print(num)
        inner()
        print(num)
    outer()
    以上实例输出结果:
    100
    100

    函数的嵌套和作用域链

      函数的嵌套调用

    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
    
    # max4(23,-7,31,11)
    
    函数的嵌套调用
    def f1():
        print("in f1")
        def f2():
            print("in f2")
    
        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()
    
    作用域链(一)
    def f1():
        a = 1
        def f2():
            def f3():
                print(a)
            f3()
        f2()
    
    f1()
    
    作用域链(二)
    def f1():
        a = 1
        def f2():
            a = 2
        f2()
        print('a in f1 : ',a)
    
    f1()
    
    作用域链(三)

     nonlocal关键字

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

    函数名的本质

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

    1.可以被引用

    def func():
        print('in func')
    
    f = func
    print(f)

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

    def f1():
        print('f1')
    
    
    def f2():
        print('f2')
    
    
    def f3():
        print('f3')
    
    l = [f1,f2,f3]
    d = {'f1':f1,'f2':f2,'f3':f3}
    #调用
    l[0]()
    d['f2']()
    
    函数被当作容易类型的元素

    3.可以当作函数的参数和返回值

    *不明白?那就记住一句话,就当普通变量用

    第一类对象(first-class object)指
    1.可在运行期创建
    2.可用作函数参数或返回值
    3.可存入变量的实体
    

      闭包

    def func():
        name = 'eva'
        def inner():
            print(name)
    

      

    闭包函数:

    内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
    #函数内部定义的函数称为内部函数

    由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!

    我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?

    是不是直接就把这个函数的名字返回就好了?

    这才是闭包函数最常用的用法

    def func():
        name = 'eva'
        def inner():
            print(name)
        return inner
    
    f = func()
    f()

    判断闭包函数的方法__closure__

    #输出的__closure__有cell元素 :是闭包函数
    def func():
        name = 'eva'
        def inner():
            print(name)
        print(inner.__closure__)
        return inner
    
    f = func()
    f()
    
    #输出的__closure__为None :不是闭包函数
    name = 'egon'
    def func2():
        def inner():
            print(name)
        print(inner.__closure__)
        return inner
    
    f2 = func2()
    f2()
    def wrapper():
        money = 1000
        def func():
            name = 'eva'
            def inner():
                print(name,money)
            return inner
        return func
    
    f = wrapper()
    i = f()
    i()
    
     闭包嵌套
    from urllib.request import urlopen
    
    def index():
        url = "http://www.xiaohua100.cn/index.html"
        def get():
            return urlopen(url).read()
        return get
    
    xiaohua = index()
    content = xiaohua()
    print(content)
    
    闭包函数获取网络应用

    本章小结

    命名空间:

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

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

    小范围的可以用大范围的
    但是大范围的不能用小范围的
    范围从大到小(图)

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

    函数的嵌套:

      嵌套调用

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

    函数名的本质:

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

    闭包:

      内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数

  • 相关阅读:
    每日一剂 14-6-6
    每日一剂 14-6-5
    每日一剂 14-6-4
    每日一剂 14-5-30
    Maven清理 .lastUpdated文件
    Docker 将项目做成镜像部署在docker中
    Docker 镜像拷贝到 正式环境运行
    Docker 安装 Tomcat
    Docker 安装 ActiveMq
    Docker 安装 nginx
  • 原文地址:https://www.cnblogs.com/zhangningyang/p/7239987.html
Copyright © 2011-2022 走看看