• Python 生成器


    列表生成式

    a = [x for x in range(10)]
    print(type(a))
    print(a)
    
    运行结果:
    <class 'list'>
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    再来一个例子:

    a = [x*2 for x in range(10)]  # 先执行 x in range(10) 得出的每个值,再依次计算 x * 2 最后组成一个列表。
    
    print(a)
    
    运行结果:
    [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    

    生成器

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。如果列表元素可以按照某种算法推算出来,用到才创建,在 Python 中这种称为生成器:generator。就像厨师一样,用到了才做菜。生成器是一种特殊的迭代器,生成器自动实现了“迭代器协议”(即__iter__和next方法),不需要再手动实现两方法。生成器在迭代的过程中可以改变当前迭代值,而修改普通迭代器的当前迭代值往往会发生异常,影响程序的执行。
    创建生成器方法一:

    a = (x for x in range(4))
    print(a)                    # 打印 a 的类型 generator object
    
    print(a.__next__())         # 获取生成器的第一个值 __netx__() 这个特殊方法不建议使用
    print(next(a))              # 获取生成器的下一个值, 等价于 a.__next__(); python 2.x 用 a.next() 方法
    print(next(a))
    print(next(a))
    
    print(next(a))              # 当生成器的值取完后,会报 StopIteration 错误
    
    运行结果:
    <generator object <genexpr> at 0x000002249CCA1200>
    
    0
    1
    2
    3
    
    StopIteration
    

    创建生成器方法二:

    def foo():
        print('ok')
        yield 1             # 返回一个 1
    
    a = foo()
    print(a)                # 打印类型
    b = next(a)             # 获取返回值,执行 next(a)的时候执行了 print('ok')
    print(b)
    
    运行结果:
    <generator object foo at 0x000001A5AE421200>
    ok
    1
    

    使用 for 迭代生成器
    注:可迭代对象是指拥有 iter 方法的对象。例如: 列表,元组,字典

    a = (x for x in range(4))
    for i in a:
        print(i)
    
    运行结果:
    0
    1
    2
    3
    

    斐波拉契数列

    def fib(max):
        n, before, after = 0, 0, 1
        while n < max:
            yield after                                   # 返回一个 after 值
            before, after = after, before + after         # 这里会优先计算出右边的表达式的结果:
                                                          # 第一次循环时 before, after = 1, 1
            n += 1
    
    res = fib(5)                                          # 生成一个生成器
    print(next(res))
    print(next(res))
    print(next(res))
    print(next(res))
    print(next(res))
    
    运行结果:
    1
    1
    2
    3
    5
    

    使用 send 方法传入参数

    def bar():
        print('ok1')
        count = yield 1         # 先返回 1 后,从 send 中接收 8 赋值给变量 count 
        print(count)
    
        print('ok2')
        yield 2
    
    b = bar()
    #b.send(None)               # 跟 next(b) 作用一样,第一次 send 前如果没有 next, 只能传一个 send(None)
    print(next(b))              # 打印 yield 1 返回的 1
    print(b.send(8))            # send(8) 进入 yield 1 处,把 8 赋值给 count 
    
    运行结果:
    ok1
    1
    8
    ok2
    2
    

    使用文件读取,找出文件中最长的行数

    文件 1.txt 内容为: 
    111111
    222
    333
    4444
    
    res = max(len(x.strip()) for x in open('1.txt', 'r'))
    print(res)
    
    运行结果:
    6
    
  • 相关阅读:
    2014-写给明年现在的自己
    DDD 领域驱动设计-Value Object(值对象)如何使用 EF 进行正确映射
    DDD 领域驱动设计-在动手之前,先把你的脑袋清理干净
    醍醐灌顶:领域驱动设计实现之路
    拨乱反正:DDD 回归具体的业务场景,Domain Model 再再重新设计
    设计窘境:来自 Repository 的一丝线索,Domain Model 再重新设计
    No zuo no die:DDD 应对具体业务场景,Domain Model 重新设计
    拨开迷雾,找回自我:DDD 应对具体业务场景,Domain Model 到底如何设计?
    【记录】GitHub/TortoiseGit 修改邮箱/提交者
    死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?
  • 原文地址:https://www.cnblogs.com/klvchen/p/8805978.html
Copyright © 2020-2023  润新知