• 第七章:Python匿名函数和装饰器


    一:匿名函数(lambda)及其应用

    (1)匿名函数(lambda)

    匿名函数:在Python中,可以使用lambda创建匿名函数,与普通函数相比,匿名函数最大的特点就是没有名字。注意

    • lambda只是一个表达式,而不是一个代码块
    • 匿名函数有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数
    • 注意区别C/C++中的内联函数,它的目的是为了提高效率

    例如下面例子中,分别用普通函数和匿名函数编写

    https://www.runoob.com/w3cnote/python-func-decorators.html
    def add(x, y):
        return x+y
    
    anonymous_function = lambda x,y:x+y
    
    print(add(1, 2))
    print(anonymous_function(1, 2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    (2)map函数

    map函数:map函数可以根据你提供的函数对指定的序列做出映射。如下

    map(function, iterable,...)
    
    • 1

    它最终会返回一个迭代器

    例如下面的例子中,有一个函数square,其作用是返回某个数的平方。如果现在有一个列表,需要对其中的所有元素都做平方,那么一般的写法是这样的

    def square(a):
        return a**2
    
    
    list1 = [1, 2, 3, 4, 5]
    print(list1)
    
    for i, x in enumerate(list1):
        list1[i] = square((x))
    
    print(list1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    而使用map后,可以简化为

    def square(a):
        return a**2
    
    
    list1 = [1, 2, 3, 4, 5]
    print(list1)
    temp = map(square, list1)
    print(temp)
    print(list(temp))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    当然这样写还是比较麻烦,map一般会和lambda结合在一起使用

    list1 = [1, 2, 3, 4, 5]
    print(list1)
    temp = map(lambda x:x**2, list1)
    print(temp)
    print(list(temp))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    (3)reduce函数

    reduce函数:它会对参数序列中元素进行累积。如下

    from functools import reduce
    reduce(function, iterable, initializer])
    
    • 1
    • 2
    • function – 函数,有两个参数
    • iterable – 可迭代对象
    • initializer – 可选,初始参数

    具体来说,它会用传给reduce中的函数function(有两个参数)先对集合中的第1、2个元素进行操作,得到结果后再与第三个数据用function函数运算,最后得到一个结果

    例如下面的例子中,它计算的是list1中所有元素的累加结果

    from functools import reduce
    
    list1 = [1, 2, 3, 4, 5]
    sum1 = reduce(lambda x, y: x+y, list1)
    sum2 = reduce(lambda x, y: x+y, list1, 5)  # 有初始值
    print(sum1)
    print(sum2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    (4)filter

    filter函数:filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。如下

    filter(function, iterable)
    
    • 1
    • function:判断函数
    • iterable:可迭代对象

    具体来说,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中

    如下,把列表中所有小于0的元素给过滤掉

    list1 = [1, -2, 3, 0, -6, 19, -2]
    result = filter(lambda x: True if x >= 0 else False, list1)
    print(list(result))
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    二:装饰器(Decorators)

    • 注意: 装饰器十分重要,在Python相关项目中会频繁使用

    装饰器(Decorators):装饰器本质也是一个函数,它的作用是用来修改其他函数的功能

    (1)关于Python中函数的再说明

    装饰器从语法结构上来看就是一个嵌套函数,也即函数内部定义函数。关于函数这里有两点大家可能感觉会比较陌生,但是它的确是可行的

    • 函数不仅仅可以返回数字、字符串等,而且还可以返回函数
    • 函数也可以作为另一个函数的参数传递进去
    def function_outside(x=1):
        def function_inside_a():
            return "现在function_inside_a函数内部"
    
        def function_inside_b():
            return "现在function_inside_b函数内部"
    
        if x == 1:
            return function_inside_a  # 返回函数
        else:
            return function_inside_b  # 返回函数
    
    
    result = function_outside(1)
    print(result)
    print(result())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    def a():
        return "函数a运行"
    
    def before_a(func):
        print("函数before_a运行")
        print(func())
    
    before_a(a)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    (2)装饰器基本原理

    其实在前面的例子中,我们已经完成了一个装饰器,其语法格式如下

    def decorator(func):
    	def wrapper():
    		pass
    		return
    	return wrapper
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如下,有一个函数叫做test_function()在运行时它只会打印“这是一个测试函数”字样,现在有了新的需求:希望运行时不仅仅要出现这一行字样,而且在其前后还要分别显示程序运行时的时间戳。这里直接在函数内部修改其实并不合理,因为这样做破坏了封装性,所以我们可以利用装饰器来完成

    import time
    
    def decorator(func):
        def wrapper():
            print(time.time())
            func()
            print(time.time())
        return wrapper
    
    def test_function():
        print("这是一个测试函数")
    
    
    test_function()
    print("----------------------------------------------")
    print(decorator(test_function)())  # 装饰器
    print("----------------------------------------------")
    test_function()  # 函数本身并未被修改
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    (3)@语法糖

    在上面的叙述中,我们并没有使用到@符号,@ 符号就是装饰器的语法糖,它放在函数开始定义的地方,这样函数便可以直接调用

    import time
    
    def decorator(func):
        def wrapper():
            print(time.time())
            func()
            print(time.time())
        return wrapper
    
    @decorator
    def test_function():
        print("这是一个测试函数")
    
    
    test_function()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    (4)*args、**kwargs

    如果业务逻辑函数test_function()带有参数,那么可以在定义wrapper函数的时候指定参数

    import time
    
    def decorator(func):
        def wrapper(x):  # 参数
            print(time.time())
            func(x)  # 参数
            print(time.time())
        return wrapper
    
    @decorator
    def test_function(x):
        print("这是一个测试函数"+str(x))
    
    
    test_function(1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    如果有两个、三个甚至是多个参数,又或者说不知道参数到底有多少个时,可以用*args代替

    import time
    
    def decorator(func):
        def wrapper(*args):  # 参数
            print(time.time())
            func(*args)  # 参数
            print(time.time())
        return wrapper
    
    @decorator
    def test_function(x, y):
        print("这是一个测试函数" + str(x) + "  " + str(y))
    
    
    list1 = [1, 2, 3, 4, 5]
    test_function(1, list1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    当然如果有关键字参数时,则可以使用kwargs**

    import time
    
    def decorator(func):
        def wrapper(*args, **kwargs):  # 参数
            print(time.time())
            func(*args, **kwargs)  # 参数
            print(time.time())
        return wrapper
    
    @decorator
    def test_function(x, y=1, z=2):
        print("这是一个测试函数" + str(x) + "  " + str(y) + "  " + str(z))
    
    
    test_function(1, 2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

  • 相关阅读:
    五种I/O模型
    (初阶)指针
    论文初稿写到什么程度才算合格?
    什么是懦弱型人格?懦弱的原因和改变方法
    消息订阅与发布
    Flask 上传文件,requests通过接口上传文件
    MYSQL入门与进阶(十)
    BUFLAB
    亚马逊测评工作室应该如何开展,需要准备哪些?
    【重拾计划】深搜&广搜 | luogu P1135 奇怪的电梯
  • 原文地址:https://blog.csdn.net/qq_39183034/article/details/126694719