zoukankan      html  css  js  c++  java
  • python 生成器、迭代器

    1. 生成器

    1. 列表生成式

    对于一个列表,如果你想要把列表的每个元素进行*2的操作,要么是使用for循环进行操作,还有就是可以使用列表生成式

    for 循环:

    num = [1,2,3,4,5]
    num2= []
    for n in num:
        n=n*2
        num2.append(n)
    print(num2)

    列表生成式:

    num = [1,2,3,4,5]
    num2 = [i * 2 for i in num]   # 对于num中的i,每个i*2,放到新的列表中
    num3 = [i *2 for i in num if i<4] # 还可以加判断,对于num中的i,如果i<4,就i*2,然后放到新列表中
    print(num2)
    print(num3)

    2. 简单的生成器

    生成器,就是将列表生成式的 [] 改成 () 就行。

    num = (i * 2 for i in range(1,10))
    print(num)      # generator对象
    print(num.__next__())  # 通过__next__()方法取值,一次取一个
    print(next(num))       # 通过next()方法取值,一次取一个
    for i in num:         # 通过循环遍历,获取所有值
        print(i)

    3. 复杂的生成器

    复杂的生成器。上面的生成器是很简单的,才能用列表生成式实现,但是如果复杂的呢,例如斐波拉契数列,就需要使用 yield 了

    def fib(num):               # 带有yield关键字,是生成器
        n,a,b = 0,0,1
        while n<num:
            yield b            # 每次调用,执行到yeild就停止,相当于return b,
                                # 下一次调用__next__方法时,从yield的下一行开始执行
            a,b = b,a+b
            n+=1
        return 'done.'       '''注意,for循环遍历迭代器无法执行到这一句代码,只能通过异常处理捕获'''
    
    
    f = fib(10)
    print(f.__next__())
    print(f.__next__())print('------------')
    
    # 遍历迭代器的内容:方法一,无法获取返回值(因为每次for循环,遇到yield都相当于return一个值,当最后一次yield时,整个函数就通过yield结束了,无法执行下面的语句,故无法获取真正的return语句)
    # for i in f:
    #     print(i)
    
    # 遍历迭代器的内容:方法二,通过捕获异常获取返回值
    while True:
        try:
            x = next(f)  # 等同于 f.__next__()
            print(x)
        except StopIteration as e:  # 通过异常处理获取返回值
            print(e.value)          # e的值是return的内容
            break

    3.通过yield给生成器传值

    def consumer(name):
        print('%s来吃包子了!'% name)
        while True:
            baozi = yield
            print('%s包子被%s吃了!'%(baozi,name))
    
    c = consumer('Wang')
    c.__next__()   # 第一次执行迭代器,执行到yield停止,目的是执行:print('%s来吃包子了!'% name)
    c.send('1个')  # 给yield传递值,并从上次停止的地方(yield处)开始执行下面的代码

    4. 生成器的并行

    import time
    def consumer(name):
        print('%s来吃包子了!'% name)
        while True:
            baozi = yield
            print('%s包子被%s吃了!'%(baozi,name))
    
    # c = consumer('Wang')
    # c.__next__()   # 第一次执行迭代器,执行到yield停止
    # c.send('1个')  # 给yield传递值,并继续上次停止的地方开始执行
    
    def maker(name):
        A = consumer('A')
        B = consumer('B')
        next(A)   # A.__next__() ,执行生成器,遇到yield返回,目的是打印: %s来吃包子了!
        next(B)
        print('%s开始做包子了!'%name)
        for i in range(5):
            time.sleep(0.7)
            print('%s第%s笼做了10个包子!' %(name,i+1))
            A.send('5个')
            B.send('5个')
    
    maker('C')

    2. 迭代器

    迭代对象: 能用for循环进行遍历的对象,都是迭代对象,可迭代的
    迭代器: 凡是能用next调用的对象,才是迭代器,所以生成器是迭代器,但是迭代器不一定非得是生成器
    from collections.abc import Iterable
    from collections.abc import Iterator
    
    # 判断是否可迭代
    print(isinstance('aaaa',Iterable))
    print(isinstance([1,2,3],Iterable))
    print(isinstance({1:2,3:4},Iterable))
    print(isinstance((1,2,3),Iterable))
    
    # 判断是否是迭代器
    print(isinstance('aaaa',Iterator))
    print(isinstance([1,2,3],Iterator))
    print(isinstance({1:2,3:4},Iterator))
    print(isinstance((1,2,3),Iterator))
    print(isinstance((x*1 for x in range(10)),Iterator))
    
    # 转换成迭代器
    a = iter([1,2,3,4,5])
    print(next(a))
    print(next(a))
  • 相关阅读:
    建立连接数据库时要输入哪些信息?
    如何建立一个JDBC程序?
    如何在网上找MySQL数据库的JDBC驱动jar包?
    gorm连接mysql数据库
    Django ORM的骚操作
    Python 发送企业微信单发和群发机器人
    python获取指定间隔日期列表
    表名小写_set.all()再根据字段过滤
    foreignkey相关的参数
    Django 模型层-多表操作
  • 原文地址:https://www.cnblogs.com/wztshine/p/11764726.html
Copyright © 2011-2022 走看看