• 【python基础】生成式、装饰器、高阶函数


    一、生成式

    (1)、列表生成式

    列表生成式就是一个用来生成列表的特定语法形式的表达式。是Python提供的一种生成列表的简洁形式,可快速生成一个新的list。
    1、使用方法

    普通的语法格式:[exp for iter_var in iterable]
    带过滤功能语法格式: [exp for iter_var in iterable if_exp]
    带过滤功能语法格式: [exp for iter_var in iterable if_exp]
    
    • 1
    • 2
    • 3

    2、基本运用
    它可以将繁琐的方法1简化为方法2

    方法1

    import string
    import random
    codes = []
    for count in range (100):                            #循环100次,每次都任意生成4个字符串
        code = "".join(random.sample(string.ascii_letters,4))
        codes.append(code)
    print(codes)
    
    #结果
    ['MIFp', 'zJct', 'KpNB', 'afcS', 'zCnv', 'nzgH', 'IlhR', 'UHJk', ....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    方法2

    codes = [ "".join(random.sample(string.ascii_letters,4)) for i in range(100)]
    print(codes)
    #结果
    ['mnLM', 'LVKe', 'ntlM', 'BjYl', 'KIAt', 'gRBl', 'QiqH', ...
    
    • 1
    • 2
    • 3
    • 4

    3、练习题
    找出1到100里面可以被3整除的数
    方法1

    nums = []
    for num in range(1,100):
        if num % 3 == 0:
            nums.append(num)
    print(nums)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    方法2
    利用公式生成器

    nums = [num for num in range(1,100) if num % 3 == 0]
    print(nums)
    
    • 1
    • 2

    (2)、集合生成式

    集合生成公式如下

    result = {i**2 for i in range(10)}
    print(result)
    #结果
    {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
    
    • 1
    • 2
    • 3
    • 4

    (3)、字典生成式

    字典生成式如下

    result={i:i**2 for i in range(10)}
    print(result)
    #结果
    {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
    
    • 1
    • 2
    • 3
    • 4

    二、生成器

    (1)、生成器特点

    在python中一边循环一边计算的机制叫做生成器
    在这里插入图片描述
    运用场景
    在这里插入图片描述

    (2)、使用方法

    1、生成器的方法
    方法1:实现的第一种方法(将生成式改写为生成器即可)

    nums = (i**2 for i in range(1000))
    print(nums)
    #结果
    <generator object <genexpr> at 0x0000018FFF234900>
    
    • 1
    • 2
    • 3
    • 4

    上面的不太方便查看,可以用下面这种方法查看值

    nums = (i**2 for i in range(1000))
    for num in nums:
    print(num)
    #结果
    0
    1
    4
    9
    16
    25
    36
    。。。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方法2:yield关键字

     return:函数遇到return就返回,后面的函数不会执行。
     yield: 遇到yield则停止执行代码,再次调用next方法时,从上次停止的yiled继续执行到下一个yield
    
    • 1
    • 2
    def login():
        print('step1')              # step
        yield 1                     #output
        print('step')
        yield 2
        print('step 3')
        yield 3
    # 如果函数里面有yield关键字,说明函数的返还值是一个生成器
    g = login()
    print(next(g))
    print(next(g))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    三、闭包

    (1)、了解时间戳

    import time
    start_time=time.time()    #从1970.1.1到现在的秒数
    time.sleep(2)             #休眠两秒
    end_time = time.time()    #从1970.1.1到现在的秒数
    print(end_time-start_time)
    #结果
    2.00744891166687
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (2)、闭包

    1、函数里面嵌套函数
    2、外部函数的返回值是内部函数的引用
    3、内部函数可以使用外部函数的变量

    import time
    def timeit(name):
        def wrapper():
            print('wrapper'+name)
        print('timeit')
        return wrapper
    in_fun = timeit(name = 'westos')            in_fun此时相当于wrapper函数
    in_fun()                                    相当于同时调用了内部和外部的函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    四、装饰器

    (1)、装饰器

    1、基本模板

    import time
    from functools import wraps
    def 装饰器名称(f):
        @wraps(f)                            保留被装饰器函数的帮助文档
        def wrapper(*args,**kwargs):
            #这里可以添加执行函数前的事情
            result=f(*args,**kargs)
            #执行函数之后做的事情
            return result                    返还函数给被装饰的函数
        return wrapper()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、举例

    # 装饰器:用于装饰函数的功能
    # 在不改变源代码的情况下,去添加额外功能的工具
    # 用闭包实现装饰器
    import time
    def timeit(f):
        def wrapper(x,y):
            start = time.time()
            result= f(x,y)                               #执行的是add(x,y)
            end = time.time()
            print('函数运行的时间为:%.4f'%(end-start))
            return result
        return wrapper
    
    @timeit                                              #装饰糖,这里时间上是将add函数转换为timeit(add())
    def add(x,y):
          return x+y
    
    result = add(1,3)
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3、添加wraps,可以对函数的帮助文档进行分别说明

    # 装饰器:用于装饰函数的功能
    # 在不改变源代码的情况下,去添加额外功能的工具
    # 用闭包实现装饰器
    import time
    from functools import wraps
    def timeit(f):
        """" 计时器的装饰器 """
        @wraps(f)                                      #保留被装饰函数的属性信息和帮助文档
        def wrapper(*args,**kwargs):
            start = time.time()
            result= f()                                #执行的是login()
            end = time.time()
            print('函数运行的时间为:%.4f'%(end-start))
            return result
        return wrapper
    
    @timeit                                           #装饰糖,这里时间上是将add函数转换为timeit(add())
    def login():
        """"login的帮助文档"""
        print('login')
    
    print(help(timeit))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    (2)、含参数的装饰器

    import time
    from functools import wraps
    def timeit(args='seconds'):
        def desc(f):
            """" 计时器的装饰器 """
            @wraps(f)                                                            保留被装饰函数的属性信息和帮助文档
            def wrapper(*args,**kwargs):
                start = time.time()
                result= f()                                                      执行的是login()
                end = time.time()
                if args =='seconds':
                    print(f"函数{f.__name__}运行的时间为{end-start}秒")
                elif args == 'mintues':
                    print(f"函数{f.__name__}运行的时间为{(end - start)/60}秒")
                return result
            return wrapper
        return desc
    
    @timeit(args='mintues')                                                      先实现timeit() 它将@执行desc函数,即desc=desc(login)
    def login():
        """"login的帮助文档"""
        print('login')
    
    login()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    (3)、多个装饰器

    注意修饰器的调用顺序是从下到上,先调用第二个装饰器is_permisson,再调用第一个装饰器 is_login,但是最终的结果是从上到下 ,输出一个装饰器的结果,再输出第二个装饰器的结果,最终再执行函数的结果。

    from functools import wraps
    def is_login(f):
        @wraps(f)
        def wrapper1(*args,**kwargs):
            print('is_login,用户是否登录')
            result=f(*args,**kwargs)
            return result
        return wrapper1
    
    
    def is_permisson(f):
        @wraps(f)
        def wrapper2(*args,**kwargs):
            print('is_permission,用户是否拥有权限')
            result=f(*args,**kwargs)
            return result
        return wrapper2
    
    @is_login
    @is_permisson                        注意修饰器的调用顺序是从下到上,先调用is_permisson,再调用 is_login  
    def show_hosts():
        print('显示所有的云主机')
        
    show_hosts()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    具体调用顺序如下

    1、is_permisson模块先调用
    show_host=is_permisson(show_hosts)
    得到结果show_host=wrapper2

    2、is_login模块再被调用
    show_hosts = is_login(wrapper2) (因为上一个装饰器使得show_hosts为wrapper2,因此这里传入的函数为wrapper2)
    得到结果show_hosts=wrapper1

    3、上面两步装饰完毕,进行第三步执行show_hosts函数。
    现在show_hosts的函数时wrapper1,因此执行show_hosts函数实际是执行wrapper1函数,输出为:
    ’is_login,用户是否登录‘
    然后执行f(*args,**kwargs),根据步骤2发现传进来的函数是wrapper2,因此执行wrapper2函数,输出为:
    ‘is_permission,用户是否拥有权限’
    最后执行执行f(*args,**kwargs),根据步骤1发现传进来的函数是show_hosts,因此执行show_hosts本身函数,输出为:
    ‘显示所有的云主机’

    五、内置高阶函数

    (1)、map函数

    同时并行的进行处理

    #计算x的2次方
    result = map(lambda x:x**2,[1,2,3,4])
    print(list(result))
    #结果
    [1, 4, 9, 16]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    result=map(lambda x,y:x+y,[1,2,3],[4,5,6])
    print(list(result))
    #结果
    [5, 7, 9]
    
    • 1
    • 2
    • 3
    • 4

    (2)、reduce函数

    将前者的结果作为后者的输入

    # reduce函数
    # 计算((2**3)**3)=reduce result
    from functools import reduce
    result = reduce(lambda x, y: x**y, [2, 3, 3])
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    练习·:计算1×2×。。。100

    from functools import reduce
    result = reduce(lambda x,y: x * y,list(range(1,100)))      注意一定要转换为列表
    print(result)
    
    • 1
    • 2
    • 3

    (3)、filter函数

    筛选函数
    筛选出偶数

    result=filter(lambda x:x % 2==0,[1,2,4,5])
    print(list(result))
    #结果
    # filter函数
    result=filter(lambda x:x % 2==0,[1,2,4,5])   
    print(list(result))                       输出为列表
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (4)、sorted函数

    进行数字大小排序,从小到大

    result = sorted([1,4,321,2])
    print(result)
    
    • 1
    • 2
    result = sorted([1,4,321,2],reverse=True)
    print(result)
    #结果
    [321, 4, 2, 1]
    
    • 1
    • 2
    • 3
    • 4

    根据数字是否为0进行排序
    函数里面的规则是将非01的赋予为1,然后根据 0 ,1进行排序,根据排序后进行返还真实值

    result = sorted([1,4,0,2],key=lambda x:0 if x==0 else 1)
    print(result)
    [0, 1, 4, 2]
    
    • 1
    • 2
    • 3
  • 相关阅读:
    C++内存管理(new和delete)
    如何解决找不到xinput1_3.dll无法继续执行此代码?5个解决方法分享
    八大时态-英语中的八个基本时态
    2_dataset, dataloader
    从 0 搭建 Vite 3 + Vue 3 前端工程化项目
    【JUC】信号量Semaphore详解
    php foreach变量引用的问题
    js - ES5面向对象
    盘点30个Python树莓派源码Python爱好者不容错过
    Java到底是值传递还是引用传递【通俗易懂】
  • 原文地址:https://blog.csdn.net/weixin_48819467/article/details/125492484