• Python中的函数、闭包、装饰器、lambda表达式、生成器和递归


    Python中的函数、闭包、装饰器和lambda表达式

    函数

    文章对关于函数的所有知识进行了详细的总结和讨论,希望可以给大家带来帮助
    首先是最简单的函数定义问题(后面附有代码的执行结果)

    def myfunction(name):
      for i in range(3):
          print(f"I love my {name}!")
    # myfunction(123)
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面是函数的健壮性和对于返回值的讨论

    def div(x,y):
        if y == 0:
            return "除数不能为0"
        return x / y        # 函数的返回值,使用return语句
    # print(div(2,0))
    # 如果函数没有被显示地返回一个返回值,则函数也会返回一个none值
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    函数的传入参数是有严格的对应关系的,否则输出结果就会让你意想不到

    def myfunc(s,vt,o):
        return "".join((o,vt,s))
    print(myfunc("我","打了","我爸"))
    print(myfunc("我爸","打了","我"))
    # 要注意函数形参和输出参数的位置一一对应关系
    # 使用关键字参数
    print(myfunc(o = "我",vt = "打了",s = "我爸"))
    # 且普通的参数必须写在关键字参数之前
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    在未初始化的情况下可使用默认参数

    def myfunc2(name1,name2 = "kk"):
        return "".join((name1,name2))
    print(myfunc2("jj"))
    print("\n")
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    补充一个冷门的知识点,“*”号左边是位置参数(即普通参数),
    也可以是关键字参数,但它的右边一定要关键字参数

    def abc(a,*,b,c):
        print(a,b,c)
    print("\n")
    
    • 1
    • 2
    • 3

    下面是关于参数的收集功能的实例

    def parameter(*argument):
        print("total number is {}".format(len(argument)))
        print("the first word is {}".format(argument[0]))
        print(argument)
    parameter("我","叫","大沙比")
    # 收集参数,其中的内部实现是通过元组来实现
    # 利用的是元组的打包和解包的功能
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    注意这种函数写法的时候,对于a b的定义要显示地使用关键字参数
    否则输入都会被归纳为前面的args元组中,函数自然就会报错了

    def myfunc3(*args,a,b):
        print(args,a,b)
    myfunc3(1,2,3,a = 4,b = 5)
    print("\n")
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    可以使用字典的写法建立键值对

    def myfunc4(**args):
        print(args)
    myfunc4(a = 1,b = 2,c = 3)
    print("\n")
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    对于上面的的写法,有正向使用就有反向使用

    def myfunc5(a,b,c,d):
        print(a,b,c,d)
    kwargs = {'a':1,'b':2,'c':3,'d':4}
    myfunc5(**kwargs)
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    注意局部作用域与全局变量的作用域,下面进行举例

    x = 880
    def myfunc6():
        global x
        x = 660
        print(x)
    myfunc6()
    print(x)
    # 如果想打印外面的x,使用global,可以看到函数外面的x值被永久改变了
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    嵌套函数
    且被嵌套的函数只能在外层函数之中被调用

    def funcA():
        x = 520
        def funcB():
            x = 880
            print("in funcB,x = ",x)
        funcB()
        # return funcB    # 返回函数时,只需要返回其函数名即可
        print("in funcA,x = ",x)
    funcA()     # 可以注意一下nonlocal的使用,可用之修改外层函数的变量
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    闭包

    def funA():
        x = 880
        def funB():
            print(x)
        return funB
    print(funA())
    print(funA()())
    funny = funA()
    print(funny())
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    利用闭包进行次方的运算

    def power(exp):
        def exp_of(base):
            return base ** exp
        return exp_of
    square = power(2)   # 函数相当于使用到一半,会先保存之前输入的参数
    cube = power(3)
    print(square(2),square(5))
    print(cube(2),cube(5))
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    再看一个例子进行深入的理解

    def outer():
        x = 0
        y = 0
        def inner(x1,y1):
            nonlocal x,y
            x += x1
            y += y1
            print(f"现在,x = {x},y = {y}")
        return inner
    move = outer()
    print(move(1,2))
    print(move(-2,2))
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    总结一下就是
    1.利用嵌套函数的外层作用域具有记忆能力的特性
    2.将内层函数作为返回值给返回
    在这里插入图片描述

    装饰器

    函数名作为另一个函数的参数

    import time
    def time_master(func):
        print("开始运行程序")
        start = time.time()
        func()
        end = time.time()
        print("结束程序运行")
        print(f"一共耗费的时间为{(end-start):.2f}秒")
    def myfunc7():
        time.sleep(2)
        print("hello!")
    time_master(myfunc7)
    print("\n")
    # 或者用装饰器的方法:核心是 函数当参数+闭包
    def time_master2(func):
        def call_func():
            print("开始运行程序")
            start = time.time()
            func()
            end = time.time()
            print("结束程序运行")
            print(f"一共耗费的时间为{(end - start):.2f}秒")
        return call_func    # 注意只返回的是函数名,不需要带括号
    @time_master2
    def myfunc8():
        time.sleep(2)
        print("hello!")
    myfunc8()
    print("\n")
    # 可以看到结果和上一个程序的写法是一样的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述
    多个装饰器一起使用的时候,顺序是自下向上调用

    def add2(func):
        def inner():
            x = func()
            return x + 1
        return inner
    def cube2(func):
        def inner():
            x = func()
            return x * x * x
        return inner
    def square2(func):
        def inner():
            x = func()
            return x * x
        return inner
    @add2
    @cube2
    @square2
    def test():
        return 2
    print(test())
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    多层嵌套函数时的装饰器,并给其传递参数

    def llogger(msg):
        def time_master(func):
            def call_func():
                start = time.time()
                func()
                stop = time.time()
                print(f"{msg} consums totally {(stop - start):.2f}")
            return call_func
        return time_master
    
    @llogger(msg="A")
    def func9():
        time.sleep(1)
        print("A is running...")
    
    @llogger(msg="B")
    def func10():
        time.sleep(1)
        print("B is running...")
    
    func9()
    func10()
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    lambda表达式

    一行流,lambda表达式
    语法:lambda arg1,arg2,arg3,…,argN:expression
    冒号左边是函数参数,冒号右边是函数表达式和返回值
    首先写出普通函数的用法

    def squareX(x):
        return x * x
    print(squareX(3))
    # 再用lambda表达式的写法
    squareY = lambda y : y * y
    print(squareY(3))
    print(("\n"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    # lambda也可以用在列表中
    y = [lambda x : x * x,2,3]
    y[0](y[1])
    
    • 1
    • 2
    • 3

    生成器

    每调用一次就提供一次数据,并且能记住之前的状态
    在之前的状态下继续执行下去

    def counter():
        i = 0
        while i <= 5:
            yield  i    # 产出的的意思,这里产出i
            i += 1
    print(counter())
    for i in counter():
        print(i,end=" ")    # 取消换行
    print("\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    递归

    这是一个递归的阶层函数,程序运行的结果是120

    def jieceng(n):
        if n > 1:
            return n * jieceng(n-1)
        else:
            return 1
    print(jieceng(5),"\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接下来是汉诺塔问题

    def hanoi(n,x,y,z):
        if n == 1:
            print(x,"-->",z)    # 如果只有1层,直接将金片从x移动到z
        else:
            hanoi(n-1,x,z,y)    # 将x上的n-1个金片从x移动到y
            print(x,"-->",z)    # 将最底下的金片从x移动到z
            hanoi(n-1,y,x,z)    # 将y上的n-1个金片移动到z
    n = int(input("请输入金片的片数:"))
    hanoi(n,'A','B','C')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    补充知识

     函数文档 help + 函数 即help(function)
     写函数的时候,记得写函数的说明,形式如下
     '''
     功能:******
    参数:******
    返回值:******
    '''
    def times(s:str,n:int) -> str:
    return str * n
    冒号后面的str和int只是类型注释,表示希望输入的参数的类型
    
    内省(注意使用面向对象的方法调用)
    查看函数名 __name__
    查看内容 __annotations__
    查看函数文档__doc__
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    高阶函数

    import functools
    比如 reduce,partial(偏函数)等
    wraps(func) 装饰器的进阶

  • 相关阅读:
    Git 分布式版本控制工具01:Git介绍+下载+安装
    AtCoder Beginner Contest 237 VP补题
    浣熊算法改进的深度极限学习机DELM的回归预测
    精准营销!用机器学习完成客户分群!
    基于 jasypt 实现spring boot 配置文件脱敏
    如何在 HarmonyOS 对数据库进行备份,恢复与加密
    Spring Boot中消息是什么?同步异步消息是啥/都包含那些技术?Activate MQ消息怎么整合
    Blazor Bootstrap 组件库地理定位/移动距离追踪组件介绍
    双指针——移动零
    Python networkX共现图,通过LDA主题关键词共现
  • 原文地址:https://blog.csdn.net/wlfyok/article/details/126794030