zoukankan      html  css  js  c++  java
  • 013.Python之函数嵌套、名称空间与作用域、闭包函数

    一、函数嵌套

    (一)什么是函数嵌套

    在一个函数内又定义了另外一个函数。

    def f1():
        def f2():
            print("from f2")
    
        f2()
        x = 1111
        return x
    
    f1()  # from f2
    print(f1())  # from f2  函数运行时输出的值
                 # 1111  函数的返回值
    
    ===============================================================================
    def f1():
        def f2():
            print('from f2')
        return f2
    
    res=f1()
    print(res)  # <function f1.<locals>.f2 at 0x000002EB71159040>   f2的内存地址
    res()   # from f2
    
    ===============================================================================
    import math
    
    def circle(radius,mode):
        def perimiter(radius):
            return 2 * math.pi * radius
    
        def area(radius):
            return math.pi * (radius ** 2)
        if mode == 1:
            return perimiter(radius)
        elif mode == 2:
            return area(radius)
    
    print(circle(18,1))  # 113.09733552923255
    print(circle(18,2))  # 1017.8760197630929
    

    (二)函数嵌套的调用

    在调用一个函数的过程中又调用了其他函数。

    def max2(x, y):
        if x > y:
            return x
        else:
            return y
    
    
    def max4(a, b, c, d):
        res1 = max2(a, b)
        res2 = max2(res1, c)
        res3 = max2(res2, d)
        return res3
    
    
    print(max4(1,2,3,4))  # 4
    

    二、名称空间与作用域

    (一)名称空间

    名称空间就是存放名字的地方

    1.内置名称空间

    存放的是python解释器自带的名字,如len、print、input等。

    生命周期:解释器启动则创建,解释器关闭就销毁。

    2.全局名称空间

    内置以及函数内的名字之外的名字都存放于全局名称空间中。

    生命周期:运行顶级代码/主流水线则创建,顶级代码/主流水线结束则销毁。

    # foo = 内存地址
    def foo():  # foo本身也是全局的
        z = 111
    
        # f1=内存地址
        def f1():
            pass
    
    if True:    # if语句是全局的
        aaa = 33
    

    3.局部名称空间

    函数内的名字。

    生命周期:函数调用时则创建,函数调用完毕则立即销毁。

    def f1(x, y):
        z = 3
        def f2():
            m=444
            n=5555
        f2()
    
    f1(1, 2)
    print(f1(1, 2))  # None 没有返回值,默认None
    

    (二)名称空间名字的查找顺序

    查找顺序:基于当前所在的位置向上查找。

    # 局部-》外层套的局部-》外层套的局部-》....-》全局-》内置
    
    # 示范1:站在全局进行查找
    input = 333
    
    def f1():
        input = 444
    
    f1()
    print(input)  # 333
    
    # 示范2:站在局部进行查找
    
    def f1():
        # input = 4444
        print(input)
    
    input = 333
    
    f1()  # 333
    
    def f1():
        input = 4444
        print(input)
    
    input = 333
    
    f1()  # 4444
    
    # 示范3
    # 3.1
    def f1():
        input = 444
        print(input)
    
    def f2():
        input = 555
        print(input)
    
    input = 333
    
    f1()  # 444
    f2()  # 555
    
    # 3.2
    def f1():
        input = 444
        print(input)
    
    def f2():
        # input = 555
        print(input)
    
    input = 333
    
    f1()  # 444
    f2()  # 333
    
    # 3.2
    def f1():
        input = 444
        print(input)
    
    def f2():
        # input = 555
        print(input)
    
    # input = 333
    
    f1()  # 444
    f2()
    
    # 示范4:
    # 示范4.1:
    def f1():
        input = 444
        def inner():
            input = 555
            print(input)
        inner()
    input = 333
    f1()  # 555
    
    # 示范4.2:
    def f1():
        input = 444
        def inner():
            # input = 555
            print(input)
        inner()
    input = 333
    f1()  # 444
    
    
    # 示范4.3:
    def f1():
        # input = 444
        def inner():
            # input = 555
            print(input)
        inner()
    input = 333
    f1()  # 333
    
    # 示范4.4:
    def f1():
        # input = 444
        def inner():
            # input = 555
            print(input)
        inner()
    # input = 333
    f1()  # <built-in function input>
    
    # 强调:名称空间的"嵌套关系"是函数定义阶段、也就是检测语法的时候就确定的,与调用为无关。
    x = 111
    
    def f1():
        print(x)
    
    def f2():
        x = 222
        f1()
    
    f2()  # 111
    
    # 示范5:
    
    def f3():
    
        print(x)
        x = 33333
    
    x=222
    f3()   # UnboundLocalError: local variable 'x' referenced before assignment
    # 定义函数的时候,print(x)中x是局部作用域中的x,但是在调用的时候,x还没定义,也不能向上查找,所以报错,无法执行。
    

    (三)作用域

    1.全局作用域

    # 全局作用域:内置名称空间、全局名称空间
    #       全局存活、全局有效
    

    2.局部作用域

    # 局部作用域:局部名称空间
    #       临时存活,局部有效
    

    (四)函数的参数传递都是值拷贝

    # 示范1:对全局定义的不可变类型,不可以在函数内直接修改
    x = 10
    
    def func(a): # a=10的内存地址
        a = 123
    
    func(x) # x=10的内存地址
    
    print(x)  # 10
    
    # 示范2:对全局定义的可变类型,可以在函数内直接修改
    x = []
    
    def func(a): # a=列表的内存地址
        a.append(11111)
        # a=123
    
    func(x) # x=列表的内存地址
    
    print(x)  # [11111]
    
    # 示范3:在函数内修改全局的不可变类型
    x = 10
    l = []
    
    def func():
        global x
        x = 666
        l.append(1111)
    
    func()
    print(x)  # 666
    print(l)  # [1111]
    
    # 示范4:nonlocal(了解)
    x = 10
    def f1():
        x=11
        def f2():
            # global x
            nonlocal x
            x=66666
        f2()
        print("f1内的x===》",x)
    
    
    f1()  # f1内的x===》 66666
    print(x)  # 10
    

    三、闭包函数

    (一)什么是闭包函数

    闭包函数,即函数对象+函数嵌套定义+名称空间与作用域。

    闭:指的是定义函数内的函数。

    包:指的内函数引用了外函数的变量。

    def outter():
        x = 1111
    
        def inner():
            print(x)
    
        return inner  # 千万不要加括号
    
    f = outter()
    # print(f)  # <function outter.<locals>.inner at 0x000001ACE6E79040>
    
    def f3():
        x=222222
        f()
    
    f3()  # 1111
    

    (二)为函数体代码传参的两种方式

    1.方式一:直接通过参数的方式传入

    def func(x):
        print(x)
    
    func(1)
    func(2)
    func(3)
    

    2.方式二:通过闭包函数传入

    def outter(x):
        # x = 2
    
        def func():
            print(x)
    
        return func  # 一定不要加括号
    
    f1 = outter(1)
    f2 = outter(2)
    f3 = outter(3)
    
    f1()
    f2()
    f3()
    
  • 相关阅读:
    关于OutputStream的write方法FAQ(from bbs.csdn.net)
    【Java】对文件或文件夹进行重命名
    [复习] JAVA 遍历目录 (递归调用和非递归)
    [科普]关于文件头的那些事
    Intellij IDEA和EclipsE之间的的全面对比
    为什么43%前端开发者想学Vue.js
    Chrome调试ECMAScript之断点debug技巧大全!
    如何Vue-cli开始使用在Vue.js项目中启动TDD(测试驱动开发)
    toString() 和 (String) 以及 valueOf() 三者的对照关系[java]
    java打印和重写toString
  • 原文地址:https://www.cnblogs.com/huluhuluwa/p/13155353.html
Copyright © 2011-2022 走看看