• 4. 函数参数变量闭包递归


    1.函数描述

    # ### 函数 
    """
    (1)函数的定义:
        功能 (包裹一部分代码 实现某一个功能 达成某一个目的)
    (2)函数特点:
        可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
    """
    
    # (3) 函数的基本格式
    """
    # 函数的定义处
    def func():
        code1....
        code2....
    
    # 函数的调用处
    func()
    """
    # 函数的定义处
    def func():
        print("今天是好日子")
    
    # 函数的调用处
    func()
    
    # (4) 函数的命名
    """
              函数的命名
    字母数字下划线,首字符不能位数字
    严格区分大小且,且不能使用关键字
    函数命名有意义,且不能使用中文哦
    
    驼峰命名法:
    (1)大驼峰命名法:每个单词的首字符大写 (一般在类中起名用这样的方式, 推荐)
        mycar => MyCar   busstop => BusStop myhouse => MyHouse
        youcanyouupnocannobb => YouCanYouUpNoCanNoBb
    (2)小驼峰命名法:除了第一个单词首字符不用大写之外,剩下首字符都大写                 (函数中的命名)
        mycar => myCar  myhouse=>myHouse
        mycar => my_car  myhouse => my_house (推荐)
    """
    
    # 函数的定义处
    def cheng_fa_biao_99():
        for i in range(9,0,-1):
            for j in range(1,i+1):
                print("{:d}*{:d}={:2d} ".format(i,j,i*j),end="")
            print()
    
    # 函数的调用处
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    # cheng_fa_biao_99()
    
    for i in range(10):
        cheng_fa_biao_99()

    2.函数参数

    # ### 函数的参数 : 函数运算时,需要的值
    """
    参数:
        形参: 形式参数 (在函数的定义处)
        实参: 实际参数 (在函数的调用处)
    
    形参:(普通[位置]形参 , 默认形参 , 普通收集参数 , 命名关键字参数, 关键字收集参数)
    实参:(普通实参.关键字实参)
    
    形参 和 实参 要一一对应
    """
    
    # (1) 普通形参
    # 函数的定义处 hang,lie 普通形参
    def small_start(hang,lie):
        i = 0
        while i<hang:
            j = 0
            while j<lie:
                # 打印星星
                print("*",end="")
                j+=1
            # 打印换行
            print()
            i+=1
    # 函数的调用处  3,8 普通实参
    small_start(3,8)
    
    
    # (2) 默认形参 hang,lie 在函数定义处给与默认值
    """
        如果给与实参,那么就使用实际参数,
        如果没给实参,那么就使用参数的默认值
    """
    def small_start(hang=10,lie=10):
        i = 0
        while i<hang:
            j = 0
            while j<lie:
                # 打印星星
                print("*",end="")
                j+=1
            # 打印换行
            print()
            i+=1
    # small_start()
    small_start(4,9)
    
    # (3) 普通形参 + 默认形参 
    """默认形参必须写在普通形参的后面,语法上有要求"""
    # 函数的定义处
    def small_start(hang,lie=10):
    # def small_start(hang,lie=10):
        i = 0
        while i<hang:
            j = 0
            while j<lie:
                # 打印星星
                print("*",end="")
                j+=1
            # 打印换行
            print()
            i+=1
    # 函数的调用处
    # small_start(3)
    
    # small_start(4,8)
    
    # small_start() error  # 形参实参要一一匹配
    
    # (4) 关键字实参
    """
    (1)如果使用关键字实参进行函数调用,实参的顺序无所谓
    """
    """
    (2)如果定义时是普通形参,调用时是关键字实参,
    那么这个参数后面的所有调用方式都需要关键字实参进行调用
    """
    def small_start(hang,a,b,c,lie=10):
    # def small_start(hang,lie=10):
        i = 0
        while i<hang:
            j = 0
            while j<lie:
                # 打印星星
                print("*",end="")
                j+=1
            # 打印换行
            print()
            i+=1
    # 关键字实参 hang  和 lie 
    # small_start(lie = 12,hang = 12)
    
    # small_start(3,4,5,6,7)
    small_start(3,c=90,b=7,a=5,lie =14)

     3.收集参数

    # ### 收集参数
    """
    收集参数:
        (1) 普通收集参数 * 在函数的定义处
            专门用来收集那些多余的,没人要的普通实参,形成一个元组
            语法:def func(*args) : args => arguments
    def func(*args):
        print(args) => 返回的数据类型是元组
    """
    def func(a,b,c,*args):
        print(a,b,c)
        print(args)
        
    func(1,2,3,4,5,6,6,7,8,8,8,8,8,9)
    
    # 计算任意长度的累加和
    def mysum(*args):
        total = 0
        for i in args:
            total += i
        print(total)
    mysum(11,23,45,56,1,2)
    """
    收集参数:
        (2) 关键字收集参数 ** 在函数的定义处
            专门用来收集那些多余的,没人要的关键字实参,形成一个字典
            语法:def func(**kwargs) : kwargs => keyword arguments
    def func(**kwargs):
        print(kwargs) => 返回的数据类型是字典
    """
    def func(a=1,b=2,**kwargs):    
        print(a,b)
        print(kwargs)
    
    # 方法1
    func(99,b=99,c=4,d=90,f=78)
    # 方法2
    func(b=99,a=111,c=4,d=90,f=78)
    
    
    # 拼接任意字符串
    dictvar = {"monitor"}
    def func(**kwargs):
        str1 = ""
        str2 = ""
        dictvar = {"monitor":"班长","classflower":"班花"}
        for k,v in kwargs.items():
            print(k,v)
            if k in dictvar:
                str1 += dictvar[k]+":"+ v  + "
    "
            else:            
                str2 += v + " "
        print(str1)
        print("吃瓜群众:",str2)
    
    func(monitor="舒则会",classflower="郭一萌",eatgua1="黄花",eatgua2="李村海")

     5.命名关键词参数

    # ### 命名关键字参数
    """
    (1) def func(a,b,*,参数1,参数2....) 在*后面定义的参数就是命名关键字参数
    (2) def func(*args,参数,**kwargs) 夹在普通收集参数和关键字收集参数之间的是命名关键字参数
    如果是命名关键字参数,必须使用关键字实参来进行调用赋值
    """
    
    # 定义方法1
    def func(a,b,*,c,d):
        print(a,b)
        print(c,d)
        
    func(1,2,c=3,d=4)
    
    # 定义方法2
    def func(*args,c,**kwargs):
        print(args)
        print(c)
        print(kwargs)
    
    func(1,2,3,4,a=1,b=2,c=3)
    
    
    # 定义方法3
    def func(a,b,*,c=3):
        print(a,b)
        print(c)
    # func(1,2)
    func(1,2,c=22)
    
    # 区别于默认形参
    def func(a,b,c=3):
        print(a,b)
        print(c)
    # 三种方式皆可
    func(1,2)
    func(1,2,c=22)
    func(1,2,22)
    
    # ### * 和 ** 的魔术用法
    """
        在函数的定义处:* ** 相当于打包操作 (一个是元组,一个是字典)
        在函数的调用处:* ** 相当于解包操作 (把里面的元素一个一个拿出来,当成实参调用赋值了)
    """
    # *
    def func(a,b,c):
        print(a,b,c)
    
    
    lst = [1,2,3]
    func(*lst)  # 相当于 func(1,2,3) 把列表里面的每一个元素都单独拿出来当成参数进行函数的调用
    
    # **
    print('--------->')
    def func(a,*,b,c,d):    
        print(a)
        print(b,c,d)
    
    
    dictvar = {"b":2,"c":3,"d":4}
    func(1,**dictvar) # 相当于 func(1,b=2,c=3,d=4) 把字典里面的每一个键值对,都拿出来,变成键=值的形式,进行关键字实参赋值操作
    
    # 扩展
    # 函数的定义处
    
    def func(a,b,*,c,d):    
        print(a,b)
        print(c,d)
    lst = [1,2]
    dictvar = {"c":3,"d":4}
    # 函数的调用处
    func(*lst,**dictvar)
    
    """
    在字典的前面加上一个*号,默认只传递键.
    一个*号 后面可以跟str list tuple set dict 常用的一般就是list
    二个**  后面可以跟dict 把键值对变成键=值得形式进行函数调用.
    """
    
    def func(a,b):
        print(a,b)
    dictvar = {"c":3,"d":4}
    func(*"pa")
    
    
    """
    函数的定义处:参数的定义有顺序:
    普通形参 -> 默认形参 -> 普通收集参数 -> 命名关键字参数 -> 关键字收集参数
    
    def func(*args,**kwawrgs):这样的形式定义函数,可以接收到所有种类的参数;
        pass
    """
    
    # 参数练习:
    def f1(a, b, c=0, *args, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    
    def f2(a, b, c=0, *, d, **kw):
        print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
    
    #(一)
    # f1(1, 2) # a=1,b=2,c=0,args=(),kw={}
    # f1(1, 2, c=3) #a=1,b=2,c=3,args=(),kw={}
    # f1(1, 2, 3, 'a', 'b') # a=1,b=2,c=3,args=(a,b),kw={}
    # f1(1, 2, 3, 'a', 'b', x=99)#a=1,b=2,c=3,args=(a,b),kw={x:99}
    # f2(1, 2, d=99, ext=None)#a=1,b=2,c=0,d=99,kw={ext:None}
    
    #(二)
    args = (1, 2, 3, 4)
    kw = {'d': 99, 'x': '#'}
    # f1(1,2,3,4,d=99,x="#")
    f1(*args, **kw) #a=1,b=2,c=3,args=(4,),kw={'d':99,x:'#'}
    
    #(三)
    myargs = (1, 2, 3)
    mykw = {'d': 88, 'x': '#'}
    f2(*myargs, **mykw) #a=1,b=2,c=3,d=88,kw={x:'#'}
    
    
    #(四) a b 普通形参  c 默认形参 *args 普通收集参数 d 命名关键字参数 kw 关键字收集参数
    def f1(a, b, c=0, *args,d,**kw):
        print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
        print(d)
    
    f1(1,2,3, 'a', 'b',d=67, x=99,y=77) #a=1,b=2,c=3,d=67,args=(a,b),kw={,x:99,y:77}

     5.return 返回值

    # ### return 函数的返回值,只出现在函数里
    """
    return 自定义返回值,如果没有写return ,默认返回None
    功能:把值返回到函数的调用处;
    (1)return 后面可以返回值 是自定义的. 除了6大标准数据类型之外,还有类 对象 函数 
    (2)如果执行了return 语句,意味着函数终止,后面的代码不执行
    """
    # (1) return 后面可以返回值 是自定义的. 除了6大标准数据类型之外,还有类 对象 函数 
    def func():
        # return 1
        # return 3.14
        # return 3+4j
        # return True
        # return [1,2,3]
        # return {"a":1,"b":2}
        pass
    res = func() # res ={"a":1,"b":2}
    print(res)
    
    res = print(1)
    print(res)
    
    # (2) 如果执行了return 语句,意味着函数终止,后面的代码不执行
    
    def func():
        print("这句话执行了1")
        print("这句话执行了2")
        return 1
        print("这句话执行了3")
        print("这句话执行了4")
    res = func()
    print(res)
    print("<============>")
    def func():
        for i in range(5):
            if i == 3:
                return i
            print(i)
    res = func()
    
    # 0 1 2
    
    # (3) 计算器小例子
    def calc(sign,num1,num2):
        if sign == "+":
            res = num1 + num2
        elif sign == "-":
            res = num1 - num2
        elif sign == "*":
            res = num1 * num2
        elif sign == "/":
            if num2 == 0:
                return "除数不能为0"
            res = num1 / num2
        return res
        
    print("<===>")
    res = calc("+",1,1)
    res = calc("-",-1,90)
    res = calc("*",52,10)
    res = calc("/",52,10)
    res = calc("/",5200,10)
    print(res)

     6.函数名的使用

    # ### 1.函数名的使用 
    # 1.函数名是个特殊的变量,可以当做变量赋值
    def func():
        print("函数名可以当成变量使用")
        
    abc = 45
    abc = func
    print(abc)
    abc()
    
    # 2.函数名可以作为容器类型数据的元素
    def func1():
        print(1)
    def func2():
        print(2)
    def func3():
        print(3)
        
    lst = [func1,func2,func3]
    for i in lst:
        i() # func1() func2() func3()
        
    
    
    # 3.函数名可以作为函数的参数
    def func1(func):
        func()
    
    def func2():
        print('woshi func2')
    
    # func形参接收到了func2这个实参函数,调用func1执行里面的代码块.调用func2()
    func1(func2)
    
    print("<===>")
    
    # 4.函数名可作为函数的返回值
    def func3(func):
        return func
    
    def func4():
        print("woshi func4")
    
    # func4这个实参被func接收到 ,执行func3代码块内容,直接return func4 ,res接收到了返回值func4
    res = func3(func4)
    res() # func4()
    
    # ### 2.__doc__或者help查看文档
    # help(print)
    res = print.__doc__
    print(res)
    
    # 如何自定义函数的文档
    # 吃大肠的过程
    def eat_big_chang(something):
        """
        功能:模拟吃大肠的过程
        参数:大肠
        返回值:吃没吃完的状态    
        """
    
        print("我是在模拟{}过程".format(something))
        print("第一步.找肠子头")
        print("第二步.把肠子头放嘴里")
        print("第三步.使劲唆")
        return "擦擦嘴,满意的放下肠子.吃完了"
    
    eat_big_chang("吃大肠")
    
    # 方法1 用 函数.__doc__
    res = eat_big_chang.__doc__
    print(res)
    
    # 方法2
    print("<===>")
    help(eat_big_chang)

     7.全局变量与局部变量

    # ### 全局变量 与 局部变量
    """
    局部变量:定义在函数内部的变量
    全局变量:定义在函数外部或者用global关键字在函数内部定义的变量
    
    作用域: 作用的范围
    
    局部变量的作用域:只限定在函数内部;
    全局变量的作用域:横跨整个文件
    """
    
    # 1.局部变量的获取 与 修改
    def func():
        a = 15
        # 获取局部变量
        print(a)
        # 修改局部变量
        a = 17
        print(a)
    func()
    # print(a) error  a局部变量值限定在函数内部使用;
    
    # 2.全局变量的获取 与 修改
    b = 100
    # 获取全局变量
    print(b)
    # 修改全局变量
    b += 200
    print(b)
    
    print("<====>")
    # 3.在函数内部可以直接获取全局变量,但是不能直接修改
    # 用global关键字,修改全局变量
    c = 50
    def func():
        global c
        print(c)
        c = 60
        print(c)
    func()
    print(c)
    
    
    # 4.在函数内部可以直接定义一个全局变量
    def func():
        global d
        d = 90
    func()
    print(d)
    
    
    # 总结:
    """
    global关键字 如果函数外部没有该变量,就是在函数内部定义一个全局变量
    global关键字 如果函数外部有该变量,那么就是在函数内部修改一个全局变量
    global用来修饰全局变量 ; 有就修改,没有就创建.
    """

     8.函数的嵌套

    # ### 函数的嵌套
    """
    函数之间允许嵌套:
        嵌套在外层的就是外函数
        嵌套在内容的就是内函数
    """
    
    
    def outer():
        
        def inner():
            print("111")
        inner()
    
    """
    (1)内部函数可以直接在函数外部调用么 不行
    (2)调用外部函数后,内部函数可以在函数外部调用吗  不行
    (3)内部函数可以在函数内部调用吗  可以
    (4)内部函数在函数内部调用时,是否有先后顺序 在定义在调用
    python 没有预加载机制:即不能提前把函数加载到内存当中.
    """
    outer()
    
    """
        def func():
            pass
        func()
        
        int a = 5 c
        int a = 6 java
        $a = 67 php
        var a = 89 js
        a = 90 python
    """
    
    # 外层是outer函数,里面有inner , inner 中还有smaller ,如果调用smaller?
    
    def outer():    
    
        def inner():
            
            def smaller():
                print(id)
                print("我是smaller函数")
            smaller()
        inner()
    outer()
    
    # LEGB 原则 (就近找变量原则)
    """
    #找寻变量的调用顺序采用LEGB原则(即就近原则)
    B —— Builtin(Python);Python内置模块的命名空间      (内建作用域)
    G —— Global(module); 函数外部所在的命名空间        (全局作用域)
    E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域)
    L —— Local(function);当前函数内的作用域            (局部作用域)
    依据就近原则,从下往上 从里向外 依次寻找
    """
    
    
    # 生命周期
    """
    内置命名空间中的所有变量 > 全局命名空间中的所有变量 > 局部命名空间中的所有变量
    """
    
    # 了解
    """
    # 命名空间 : 划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系).一共三种.
    (1)内建命名空间:解释器启动时创建,直到解释器运行结束,生存周期最长
    (2)全局命名空间:文件运行时创建,直到解释器运行结束,生存周期较长
    (3)局部命名空间:函数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短
    #命名空间的提出是为了划分和控制变量是否可见,以及生存周期的长短.
    
    #命名空间 创建顺序:(了解)
        python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
    #命名空间 销毁顺序:(了解)
        函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据
    """
    
    
    """
    # 地址相关知识点:
        -5~正无穷 int
        浮点型非负数 float
        相同的布尔值  bool
        在实数+虚数结构中永远不相同(只有虚数部分除外) complex
        相同的字符串 str
        空元组 tuple
        id() 用来获取地址
        is  / is not 针对于地址提出来,用来判断两个变量地址是否相同.
        
        var1 = 90
        var2 = 90
        print(id(var1))
        print(id(var2))
    """

     9.nonlocal

    # ### nonlocal 用来修饰局部变量
    """
    nonlocal 符合LEGB 原则, 就近原则找变量;
    (1) nonlocal 用来修改局部变量
    (2) nonlocal 会不停的寻找上一层空间所对应的值,拿来修改
    (3) 如果上一层找不到,继续向上寻找,再也找不到了,直接报错;
    """
    
    # (1) nonlocal 只能用来修改局部变量
    a = 90
    def func():
        # nonlocal a  error
        a = 80
        print(a)
    func()
    
    # (2) nonlocal 会不停的寻找上一层空间所对应的值,拿来修改
    """通过LEGB原则,可以获取到上一层空间的值,只能单纯的获取,不能直接修改
    如果想要修改 通过nonlocal 加以修饰.
    """
    def outer():
        a = 20
        def inner():
            nonlocal a
            print(a)
            a += 1
            print(a)
        inner()
    outer()
    
    # (3) 如果上一层找不到,继续向上寻找,再也找不到了,直接报错; nonlocal 只能修饰局部变量
    a = 100
    
    def outer():
        a = 100
        def inner():
            # a = 110
            def smaller():
                nonlocal a
                a += 10
                # print(a)
            smaller()
            print(a,"<=1=>")
        inner()
        print(a,"<=2=>")
    outer()
    
    
    # (4) 不通过nonlocal 是否可以改变局部变量? 可以! 需要使用列表进行操作;
    def outer():
        lst = [100,101,102]
        def inner():
            lst[0] += 1
        inner()
        print(lst)
    outer()

     10.闭包函数

    # ### 闭包函数
    """
    概念:内函数使用了外函数的局部变量,
    并且外函数把内函数返回出来的过程,叫做闭包
    这个内函数叫做闭包函数
    """
    
    # (1) 基本语法:
    def lizuqing_family():    
        father = "李嘉诚"
        def father_say():
            print("{}说了:先定他一个小目标,买一个英国伦敦".format(father))
        return father_say
    
    func = lizuqing_family() # func = father_say
    print(func)
    func() #=> father_say()
    
    # (2) 闭包函数的升级
    """
    内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长了该变量的生命周期
    """
    def liaopingping_family():
        jiejie = "马蓉"
        meimei = "马诺"
        money = 1000
        
        def jiejie_hobby():
            nonlocal money
            money -= 500
            print("买名牌包包,名牌手表,名牌狗链,.....家里的前还剩下%s"%(money))
        
        def meimei_hobby():
            nonlocal money
            money -= 400
            print("宁愿在宝马里面哭,也不愿再自行车上面撒欢.家里的钱还剩下%s"%(money))
        
        def big_guanjia():
            return jiejie_hobby,meimei_hobby # 返回一个元组
            # return (jiejie_hobby,meimei_hobby)
    
        return big_guanjia
    
    func = liaopingping_family()
    print(func)
    tup = func()
    print(tup) #(<function liaopingping_family.<locals>.jiejie_hobby at 0x000001DCD2877048>, <function liaopingping_family.<locals>.meimei_hobby at 0x000001DCD28770D0>)
    # 调用 姐姐jiejie_hobby
    jiejie =  tup[0]
    print(jiejie) #<function liaopingping_family.<locals>.jiejie_hobby at 0x0000026526B49048>
    jiejie()
    # 调用 妹妹meimei_hobby
    meimei = tup[1]
    meimei()  # <function liaopingping_family.<locals>.meimei_hobby at 0x000001DCD28770D0>

     11.闭包的特点

    # ### 闭包的特点
    """
        内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长了该变量的生命周期
    """
    def outer(val):
        def inner(num):
            return num +  val
        return inner
    
    
    func = outer(10)
    res = func(5) # func = inner() = num + val = 10 + 5 = 15
    print(res)
    
    """
    func = outer(10)
    val 接收到10这个值 return inner 
    因为内函数使用了外函数的局部变量val,val就与内函数发生绑定,延长该变量生命周期,不释放,等待下一次调用时使用
    
    res = func(5)
    num 接受到5这个值 return num + val return 5 + 10  => return 15
    """
    
    # ### 闭包的意义
    """
    闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
    模拟一个鼠标点击计数功能:
    """
    
    clicknum = 0
    def clickfunc():
        global clicknum
        clicknum += 1
        print(clicknum)
    
    # 模拟点击操作,点击一次就调用一次
    clickfunc()
    clickfunc()
    clickfunc()
    clickfunc()
    clickfunc()
    clicknum = 100
    clickfunc()
    
    
    # 用闭包函数来进行改造
    def clickfunc():
        x = 0
        def func():
            nonlocal x
            x +=1 
            print(x)
        return func
    clickfunc2 = clickfunc()
    clickfunc2() # clickfunc2() = func()
    clickfunc2() 
    clickfunc2() 
    clickfunc2() 
    clickfunc2() 
    x = 100
    clickfunc2() 

     12.locals和globals

    # ### locals 和 globals
    """ 
    locals() 获取当前作用域的所有变量
    
    如果locals在函数外:所获取的是locals(),打印返回值之前的所有内容
    如果locals在函数内:所获取的是locals(),调用之前所有内容
    """
    
    # 当前作用域在全局范围
    a = 1
    b = 2
    res = locals()
    c = 3
    print(res)
    
    
    """
    # 当前作用域在局部范围
    zz = 90
    def func():
        d = 4
        f = 5
        res = locals()
        g = 6
        print(res)
    
    func()
    """
    """
    globals 无论在函数内外,都只获取全局作用域当中的所有内容
    
    如果globals在函数外:所获取的是globals(),打印返回值之前的所有内容
    如果globals在函数内:所获取的是globals(),调用之前所有内容
    """
    # 当前作用域在全局范围
    a = 1
    b = 2
    res = globals()
    c  = 3
    print(res)
    
    # 当前作用域在局部范围
    '''
    aa = 11
    bb = 22
    def func():
        d =1 
        f = 2
        res = globals()
        z = 3
        print(res)
    cc = 33
    func() #res = globals()
    dd = 4
    '''
    
    # globals 动态的创建全局变量
    """
    globals() 返回的是系统的字典,只需要在字典里面添加键值对,就可以创建全局变量
    字典中的键 就是变量名
    字典中的值 就是变量所指代的值
    """
    dic = globals()
    print(dic)
    dic["wangwen"] = "风流倜傥,美若天仙,才华横溢,玉树临风"
    # wangwen = "风流倜傥,美若天仙,才华横溢,玉树临风"
    print(wangwen)
    
    
    # globals 批量创建全局变量
    # 创建p1~p5 5个全局变量
    def func():
        dic = globals()
        for i in range(1,6):
            # p1 ~ p5 5个键
            dic["p%d" % (i)] = i
    
    func()
    print(p1)
    print(p2)
    print(p3)
    print(p4)
    print(p5)

     13.匿名函数

    # ### 匿名函数  => lambda 表达式 
    """
    lambda 表达式: 
        用一句话来表达只有返回值的函数 
    好处:
        简洁,方便,定义函数快速简单
    语法:
        lambda 参数 : 返回值
    """
    # 1.无参的lambda表达式
    def func():
        return 123456
    
    func = lambda : 123456
    res = func()
    print(res)
    
    # 2.有参的lambda表达式
    def func(n):
        return type(n)
    res = func("1234")
    print(res)
    
    func = lambda n : type(n)
    res = func([1,2,3])
    print(res)
    
    # 3.带有条件判断的lambda表达式
    def func(n):
        if n % 2 == 0:
            return "偶数"
        else:
            return "奇数"
    
    # 4.三目运算符: 用来表达双项分支
    """
    真值 if 条件表达式 else 假值
        如果条件表达式成立,执行真值
        如果条件表达式不成立,执行假值
    """
    n = 11
    res = "偶数" if n % 2 == 0 else "奇数"
    print(res)
    
    n = 90
    func = lambda n : "偶数" if n % 2 == 0 else "奇数"
    print( func(n) )
    
    # 计算参数中的最大值
    def func(m,n):
        if m>n:    
            return m
        else:
            return n
    print( func(13,9) )
    
    
    func = lambda m,n : m if m>n else n
    print( func(-90,90) )

     14.递归函数

    # ### 递归函数
    """
    递归函数:自己调用自己的函数
    递:去
    归:回
    一去一回是递归
    
    
        
    递归的最大深度:官网说法1000层,但实际996~1000
    """
    
    # 简单递归
    def digui(n):
        print(n,"<==11==>")
        if n>0:
            digui(n-1)
        print(n,"<==22==>")
    digui(5)
    
    """
    去的过程:
        n = 5
        print(5,"<==11==>")
        5 > 0 digui(5 - 1) digui(4)
    
        n = 4
        print(4,"<==11==>")
        4 > 0 digui(4 - 1) digui(3)
    
        n = 3
        print(3,"<==11==>")
        3 > 0 digui(3 - 1) digui(2)
    
        n = 2
        print(2,"<==11==>")
        2 > 0 digui(2 - 1) digui(1)
    
        n = 1
        print(1,"<==11==>")
        1 > 0 digui(1 - 1) digui(0)
    
        n = 0
        print(0,"<==11==>")
        0 > 0  条件不满足,往下执行
        print(0,"<==22==>")
        
    回的过程: (把剩下的没走玩的代码继续执行)
        回到上一次函数的调用处第17行,从17行继续向下执行
        n = 1 print(1,"<==22==>")
        
        回到上一次函数的调用处第17行,从17行继续向下执行
        n = 2 print(2,"<==22==>")
        
        回到上一次函数的调用处第17行,从17行继续向下执行
        n = 3 print(3,"<==22==>")
        
        回到上一次函数的调用处第17行,从17行继续向下执行
        n = 4 print(4,"<==22==>")
        
        回到上一次函数的调用处第17行,从17行继续向下执行
        n = 5 print(5,"<==22==>")
        
        递归函数彻底终止.
    """
    
    """
    # 递归的最大深度 error
    def func():
        func() #[Previous line repeated 995 more times]
    func()
    """
    
    # 栈帧空间:是为了运行函数所需要开辟的空间
    """
    (1)没调用一次函数,就是开辟一个栈帧空间的过程
    每结束一次函数,就是释放一个栈帧空间的过程
    递归函数就是不停的开辟栈帧空间和释放栈帧空间的过程
    
    (2)回的过程有两种触发时机:    
        (1)当最后一层函数全部执行完毕,触发回的过程,回到上一层函数调用处
        (2)当遇到return 返回值的时候,触发回的过程,回到上一层函数调用处
        
    (3)如果递归层数过大,不推荐使用递归,如果使用,务必添加一个跳出的条件,防止内存溢出;
    """
    
    """
    # 栈帧空间彼此的数据是隔离的,彼此独立,各是各的空间
    def abc(n)
        print(n)
    abc(1)
    abc(2)
    """
    
    # 计算n的阶乘 5! = 5*4*3*2*1
    def jiecheng(n):
        if n<=1:
            return 1
        return n * jiecheng(n-1)
    res = jiecheng(5)
    print(res)
    
    """
    需要先把表达式的值算完之后,再返回
    
    # 去的过程
    n = 5 return 5 * jiecheng(5 - 1) => 5 * jiecheng(4)
    n = 4 return 4 * jiecheng(4 - 1) => 4 * jiecheng(3)
    n = 3 return 3 * jiecheng(3 - 1) => 3 * jiecheng(2)
    n = 2 return 2 * jiecheng(2 - 1) => 2 * jiecheng(1)
    n = 1 n <= 1 满足 return 1
    
    # 回的过程
    n = 2 return 2 * jiecheng(2 - 1) => 2 * jiecheng(1) => 2 * 1
    n = 3 return 3 * jiecheng(3 - 1) => 3 * jiecheng(2) => 3 * 2 * 1
    n = 4 return 4 * jiecheng(4 - 1) => 4 * jiecheng(3) => 4 * 3 * 2 * 1
    n = 5 return 5 * jiecheng(5 - 1) => 5 * jiecheng(4) => 5 * 4 * 3 * 2 * 1
    最后直接 return  5 * 4 * 3 * 2 * 1 = 120
    """
    print(jiecheng(1))
    善战者,求之于势,不责于人,故能择人而任势
  • 相关阅读:
    Thymeleaf中,将字符串作为js函数的参数
    测试开发面试题总结
    013_RomanToInteger
    Python列表中查找某个元素的索引(多个)
    Python“函数式编程”中常用的函数
    009_Palindrome Number
    Python字符串方法总结(一)
    007_Reverse Integer
    002_Add Two Numbers
    pycharm上传代码到github
  • 原文地址:https://www.cnblogs.com/NGU-PX/p/11217463.html
Copyright © 2020-2023  润新知