zoukankan      html  css  js  c++  java
  • 【python基础】生成器&迭代器

     一、生成器:generator

      按照规则去生成一定的数据

      1、列表推导式和生成器的区别

        列表推导式: 一次性生成所有满足条件的数据
        生成器: 你要一个数据, 我生成出来给你一个

      2、生成器表达式

        生成器对象 = (表达式 for item in 容器)
        生成器对象 = (表达式 for item in 容器 if 条件)
        生成器对象 = (表达式 for item in 容器 for item2 in 容器2)

      3、通过生成器对象获取数据

        (1)next(g)   

        (2)for in 依次获取生成器对象中的每个数据    

        (3) g.__next__()

        (4)send(值):给上一次生成器函数中yield的位置传递一个值

                第一次获取生成器数据时, 不能使用send()方法获取

     1 # 1、生成1-10的数据的生成器
     2 g = (x for x in range(1, 11))
     3 print(type(g))  # <class 'generator'>
     4 print(g)  # <generator object <genexpr> at 0x00000000007EA948>
     5 
     6 print(next(g))  # 1 获取g对象的数据
     7 print(next(g))  # 2
     8 print(next(g))  # 3
     9 print(next(g))  # 4
    10 
    11 for x in g:
    12     print(x)   # 5, 6, 7, 8, 9, 10
    13 
    14 # print(next(g))  # StopIteration
    15 
    16 
    17 # 2、创建一个生成器对象, 包含1-10之间的所有偶数
    18 g1 = (x for x in range(1, 11) if x % 2 == 0)
    19 
    20 print(g1)  # <generator object <genexpr> at 0x000000000260A948>
    21 print(type(g1))  # <class 'generator'>
    22 
    23 print(g1.__next__())  # 2
    24 print(g1.__next__())  # 4
    25 print(g1.__next__())  # 6
    26 print(g1.__next__())  # 8
    27 print(g1.__next__())  # 10
    28 
    29 # print(g1.__next__())  # StopIteration

    二、生成器函数

      1、关键字yield 的作用

        1、返回一个数据,如果yield后边啥也没有,返回数据为None
        2、遇到yield获取一条数据,同时暂停函数的执行,直到下一次获取数据时,从暂停的位置继续往下执行

      2、特点  

        1、生成器函数用来生成一个生成器对象
        2、生成器函数中的代码在获取对象数据时,才会被执行

     1 def func1():
     2     print("我是生成器")
     3     yield   # return 返回值
     4 
     5 
     6 g = func1()
     7 print(g)  # <generator object func1 at 0x0000000003C2CFC0>
     8 print(type(g))  # <class 'generator'>
     9 
    10 # 获取生成器对象数据的三种方式: 1, next(对象); 2,for..in 对象; 3. 对象.__next__()
    11 print(next(g))  # 我是生成器 
     None
    12 
    13 
    14 def func2():
    15     print("我是生成器")
    16     yield 0000
    17 
    18 
    19 # step1: 获取生成器对象
    20 g2 = func2()
    21 
    22 # step2: 获取数据
    23 print(g2.__next__())
    24 """
    25 我是生成器
    26 0
    27 """
    28 
    29 # print(g2.__next__())  # StopIteration
    30 
    31 
    32 def func3():
    33     print("xixi")
    34     yield "haha"
    35     print("hanhan")
    36     yield "daidai"
    37 
    38 
    39 g3 = func3()
    40 
    41 print(g3.__next__())
    42 """
    43 xixi
    44 haha
    45 """
    46 print(g3.__next__())  # 三角龙
    47 """
    48 hanhan
    49 daidai
    50 """
    51 
    52 
    53 def func4():
    54     for x in range(10):
    55         yield "我是第%d" % x
    56 
    57 
    58 g4 = func4()
    59 
    60 print(next(g4))  # 我是第0
    61 print(next(g4))  # 我是第1
    62 print(next(g4))  # 我是第2
    63 print(next(g4))  # 我是第3
    64 
    65 
    66 def func5():
    67     print("我是第5个生成器函数")
    68     child = yield "请给我xixi"
    69     print("taotao&huihui")
    70     yield child
    71 
    72 
    73 g5 = func5()
    74 # next(g5)  # "请给我一只食肉龙"
    75 print(g5.__next__())  # 1. 获取一个生成器的数据
    76 """
    77     我是第5个生成器函数
    78     请给我xixi
    79 """
    80 # TypeError: can't send non-None value to a just-started generator
    81 
    82 print(g5.send("haha"))  # 2. 给生成器函数上一个yield的位置传递一个数据(霸王龙)
    83 """
    84     taotao&huihui
    85     haha
    86 """
    87 # print(next(g5))  
    88 # print(g5.send("abc"))  # StopIteration

    三、生成器实例

     1 # 1、传递数据, 计算所有传递的数据的总和,平均值
     2 def func1():
     3     sum_num = 0  # 用来记录所有数字的和, 初始值0
     4     count = 0
     5     avg = 0  # 用来记录所有数字的平均值, 初始值0
     6     while True:
     7         num = yield (sum_num, avg)
     8         count += 1  # 每输入一个数据, 计数+1
     9         sum_num += num  # 每输入一个数据, 和累加
    10         avg = sum_num / count
    11 
    12 g1 = func1()
    13 
    14 print(g1.__next__())  # (0, 0)
    15 print(g1.send(5))  # (5, 5.0)
    16 print(g1.send(10))  # (15, 7.5)
    17 print(g1.send(100))  # (115, 38,33333333)
    18 
    19 # 2、写一个生成器, 生成斐波那契数列;
    20 # 1, 1, 2, 3, 5, 8, 13, 21, ...
    21 # a  b->2
    22 #    a  b->3
    23 def func2():
    24     a = 1  # 所求数的前两个数
    25     b = 1  # 所求数的前一个数
    26     while True:
    27         yield a  # 1, 1, 2, 3, 5,...
    28         a, b = b, a + b
    29 
    30 g2 = func2()
    31 print(g2.__next__())  # 1
    32 print(g2.__next__())  # 1
    33 print(g2.__next__())  # 2
    34 print(g2.__next__())  # 3
    35 print(g2.__next__())  # 5
    36 print(g2.__next__())  # 8
    37 print(g2.__next__())  # 11

    四、为什么生成器是迭代器

      1、概念  

        (1)可迭代对象: 实现了__iter__方法的对象就是可迭代对象

        (2)迭代器: 实现了__iter__方法和__next__方法的对象就是迭代器

        (3)生成器:函数中使用了关键字 yield 

      2、关联

        (1)迭代器 是 可迭代对象
        (2)生成器 是 可迭代对象
        (3)生成器 是 迭代器

        __iter__()方法的返回值是 迭代器
        可迭代对象.__iter__(),就会生成一个 迭代器

      3、判断对象是否可迭代

        from collections.abc import Iterable
        isinstance(对象,Iterable)

      4、for in 的底层原理

        for in 对象
        (1)调用对象的__iter__()方法,生成一个iterator迭代器  
        (2)调用迭代器对象的__next__()方法,依次获取每个数据
        (3)for in 在遇到 StopIteration 时,停止迭代

     1 # 写个迭代器, 传入一个范围(起始值, 终止值), 依次获取
     2 # 这个范围中的素数
     3 
     4 
     5 class PrimeNumber:
     6     def __init__(self, start, end):
     7         self.start = start
     8         self.end = end
     9 
    10     # 方法: 判断一个数是不是素数
    11     def isPrimeNumber(self, num):  # 参数: 你要判断是不是素数的那个数
    12         for x in range(2, num):
    13             if num % x == 0:
    14                 return False  # 返回, 函数停止执行
    15         return True
    16 
    17     def __iter__(self):  # 返回个迭代器对象: generator(迭代器)--> __iter__(), __next__()
    18         for x in range(self.start, self.end + 1):
    19             if self.isPrimeNumber(x):
    20                 yield x
    21 
    22     # yield --> 生成器函数(返回值:生成器) --> 迭代器 --> __iter__()方法返回个迭代器
    23 
    24 n3 = PrimeNumber(3, 20)
    25 for x in n3:
    26     print(x)
    27 """
    28 3
    29 5
    30 7
    31 11
    32 13
    33 17
    34 19
    35 """
    36 
    37 # step1: 调用__iter__()获取迭代器 --> 生成器
    38 # step2: 调用__next__()获取数据
    39 # step3: StopIteration停止迭代
    40 
    41 n4 = PrimeNumber(3, 20)
    42 g4 = n4.__iter__()
    43 print(g4.__next__())  # 3
     1 g = (x for x in range(10))
     2 print(g)  # <generator object <genexpr> at 0x0000000003C2CFC0>
     3 print(dir(g))  # 查看g的所有方法
     4 
     5 def func():
     6     yield "xixi"
     7 
     8 g1 = func()
     9 print(g1)  # <generator object func at 0x000000000212A548> 
    10 
    11 print(g1.__next__())  # 'xixi'
  • 相关阅读:
    C# CheckBoxList数据操作(转) 子曰
    extjs获取后台数据(asp.net) 子曰
    PHP学习系列之 环境配置
    Javah生成JNI头文件
    [转] ubuntu 终端命令
    我开博的这一年
    [原]Java web学习系列之 Java web开发中的Hibernate对象关系映射框架
    [原]Java web学习系列之开篇
    [原]android camera中的预览图片变形的解决办法
    [原]Java web学习系列之 Java web开发中数据库连接几种方法
  • 原文地址:https://www.cnblogs.com/Tree0108/p/12114267.html
Copyright © 2011-2022 走看看