zoukankan      html  css  js  c++  java
  • 闭包

    1. 函数对象

    精髓: 可以把函数当成变量去用

    函数名和变量名一样,都是指向的是内存地址

    2. 函数名的用途

    2.1 可以赋值

    把一个函数名赋值给另一个变量名

    # func=函数的内存地址
    def func():
        pass
    
    f=func        
    print(func)   # <function func at 0x000001E78F9B3EA0> 
    print(f)      # <function func at 0x000001E78F9B3EA0>
    

    2.2 当参数

    函数名也可以当做参数传给另一个函数

    def func():
        pass
    
    def foo(×):  #× = func的内存地址#
        print(x)
        x()
    
    foo(func)  #foo( func的内存地址)
    

    2.3 当返回值

    函数名也可以当做函数的返回值

    def func():
        pass
    
    def foo(x):
        return x    
    
    
    res = foo(func)
    print(res)
    

    2.4 当参数

    函数名可以当做容器类型的一个元素

    def func():
        print('func函数: ',func)
        
    l=[func,]
    print(l)
    l[0]()        # 调用func函数
    dic={ 'k1' :func}
    print(dic)
    dic['k1']()  # 调用func函数
    

    2.5 小练习

    def login():
        print('登录功能')
    
    
    def transfer():
        print('转账功能')
    
    
    def check_balance():
        print('查询余额')
    
    
    def change_password():
        print('修改密码')
    
    
    # 巧用数据类型
    dic = {
        # '1': login,
        '0': ('退出', None),
        '1': ['登录', login],
        '2': ['转账', transfer],
        '3': ['查询余额', check_balance],
        '4': ['更改密码', change_password],
        # '2': transfer,
        # '3': check_balance,
    }
    
    while 1:
        for key, value in dic.items():
            print('{} {}'.format(key, value[0]))
        choice = input('请输入编号:').strip()
        if not choice.isdigit():
            print('必须输入编号,憨批')
            continue
        if choice == '0':
            break
        if choice in dic:
            dic[choice][1]()
        else:
            print('你输入的命令不存在,憨批')
    

    3. 函数的嵌套

    3.1 函数的嵌套调用

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

    def func1():
        print("调用了func1函数")
        
    def func2():
        print("调用了func2函数")
        
    def func3():
        print("调用了func3函数")
        
        
    def func():
        func1()
        func2()
        func3()
    

    应用场景 :

    # 把各个小功能(小函数),封装到一个大功能(大函数)里面
    
    def max2(x, y):
        return x if x > y else y
    
    
    # 比较4个参数的大小
    def max4(a, b, c, d):
        # 比较a,b得到res1
        res1 = max2(a, b)
        # 比较res1,c,得到res2
        res2 = max2(res1, c)
        # 比较res2,d ,得到res3
        res3 = max2(res2, d)
        return res3
    
    
    print(max4(7838237, 9859, 949, 90))
    

    3.2 函数的嵌套定义

    在函数内定义其他的函数

    def func():
        def func1():
            pass
    
    # 举例:
    # 求圆的周长和面积,但是只在圆内调用,在其他地方不用
    from math import pi
    
    
    def circle(radius, action=None):
        "radius:半径 action为0是求周长 action为1是求面积 "
    
        def get_perimeter(radius):
            return 2 * radius * pi
    
        def get_area(radius):
            return pi * radius ** 2
    
        # 求圆的周长
        if action == 0:
            return get_perimeter(radius)
        # 求圆的面积
        elif action == 1:
            return get_area(radius)
    

    上面的应用场景比较少,函数的嵌套定义更多的用在闭包

    # 函数的嵌套定义你可以认为把一堆函数丢到一个大容器(最外面的那个函数)中
    # 同时在外部是无法访问这个函数的,只能在大容器中访问这些函数
    

    4. 闭包函数

    闭包函数也可以直接简称为闭包

    # 闭包函数 = 名称空间与作用域 + 函数嵌套 + 函数对象
    # 核心点: 名字的查找关系是以函数定义阶段为准
    

    4.1 什么是闭包函数

    # "闭"函数指的是该函数为内嵌函数         是定义在一个函数内的函数
    
    def f1():
        def f2():   # f2是闭函数
            pass
    
    # "包是在闭的基础上"
    # "包"函数指的该函数包含对外层函数(第几层无所谓)作用域名字的引用(不是对全局作用域)
    
    def f1():
        x = 111
        def f2():
            print(x)    # x就是包,f2从外层函数f1那里引用
    

    闭包函数 : 名称空间与作用域 + 函数嵌套

    def f1():
        x = 222
    
        def f2():
            print(x)
    
        f2()
    
    
    x = 111
    
    
    def foo():
        x = 333
        f1()
    
    
    foo()    # 打印2222
    

    闭包函数 : 名称空间与作用域 + 函数嵌套 + 函数对象

    def f1():
        x = 33333333333333333333
    
        def f2():
            print('函数f2:', x)
    
        return f2   # 这样一搞就有了骚操作,在全局能够访问到f2的内存地址了,就打破了
    				# 以前在外部无法访问局部的值了
    
    
    f = f1()
    
    
    # f是全局的,但是f的值是局部的
    # 牛逼之处你在全局拿到了在局部作用域的名字
    # 牛逼的实现了,在任意地方都能访问到局部的值了,打破了层级限制
    # 拖家带口的返回,每次你调用里面的x都是在局部定义的那个x
    

    4.2 为什么要有闭包

    为什么要有闭包换句话说就是闭包的应用场景有哪些?

    闭包实现了函数的另一种传参方式,虽然没有直接传参那种看上去更加简单,但是有的应用场景就是直接传参

    解决不了,那么你不要忘记还有一种闭包传参的方式

    # 先写x=3和函数f2的定义,然后用f1包起来
    def f1():
        x = 3
    
        def f2():
            print(x)
    
        return f2
    
    f = f1() #此时f指的就是f2的内存地址
    # 你可以写f,那么你也可以写成f2
    # f2 = f1()
    
    # 有的人就说了 你写成x=3不是写死了吗,那么我们可以这样写
    def f1(x):
        def f2():
            print(x)
    
        return f2
    
    # f = f1(1)
    # f = f1(2)
    # f = f1(3)  # 这样就做到了 你传几,就是几
    

    5. 两种传参方式

    一种就是直接传 还有一种就是通过闭包传

    学习闭包就是学习了另一种函数传参方式,(曲线救国),当你有一中需求是函数直接

    传参解决不了的时候,不要忘记还有闭包这种这种传参方式,下面介绍的装饰器就是

    你无法直接传参,只能通过闭包传参来解决

  • 相关阅读:
    jython resources
    Installing a Library of Jython ScriptsPart of the WebSphere Application Server v7.x Administration Series Series
    jython好资料
    ulipad install on 64bit win7 has issue
    an oracle article in high level to descibe how to archtichre operator JAVA relevet project
    table的宽度,单元格内换行问题
    Linux常用命令大全
    dedecms系统后台登陆提示用户名密码不存在
    登录织梦后台提示用户名不存在的解决方法介绍
    Shell常用命令整理
  • 原文地址:https://www.cnblogs.com/xcymn/p/14038928.html
Copyright © 2011-2022 走看看