zoukankan      html  css  js  c++  java
  • Python迭代与生成器

    迭代

    每一次对过程的重复称为一次迭代,而每一次迭代得到的结果会作为下一次迭代的初始值。例如:循环获取容器中的元素。

    可迭代对象iterable 

    1.定义:具有__iter__函数的对象,可以返回迭代器对象。

    2.语法

    -- 创建:

    class 可迭代对象名称:

      def __iter__(self):

          return 迭代器

    -- 使用:

    for 变量名 in 可迭代对象:

      语句

    3.原理:

    迭代器 = 可迭代对象.__iter__()

    while True:

        try:

            print(迭代器.__next__())

        except StopIteration:

             break

     1 list01 = [43,4,54,5,566,7,7]
     2 # for itme in list01:
     3 #   print(itme)
     4 
     5 #对象具有__iter__()方法
     6 
     7 # for原理:
     8 # 1. 获取迭代器对象
     9 iterator = list01.__iter__()
    10 # 2. 循环获取下一个元素
    11 while True:
    12   try:
    13     item = iterator.__next__()
    14     print(item)
    15 # 3. 异常处理
    16   except StopIteration:# 迭代完成
    17     break
    迭代对象

    迭代器对象iterator

    1.定义:可以被next()函数调用并返回下一个值的对象。

    2.语法

    class 迭代器类名:

        def __init__(self, 聚合对象):

            self.聚合对象= 聚合对象

        def __next__(self):

            if 没有元素:

                raise StopIteration

                return 聚合对象元素

    3.说明:聚合对象通常是容器对象。

    4. 作用:使用者只需通过一种方式,便可简洁明了的获取聚合对象中各个元素,而又无需了解其内部结构。

     1 class SkillIterator:
     2   """
     3     迭代器
     4   """
     5 
     6   def __init__(self, target):
     7     self.target = target
     8     self.index = 0
     9 
    10   def __next__(self):
    11     # 需求:将SkillManager中__list_skill的元素返回
    12     # 创建一个下标索引index,与列表的长度比较,要求下表索引不能超过列表的长度
    13     if self.index > len(self.target) - 1:
    14       raise StopIteration()
    15     # 下标每次+1,并将每次下标元素返回去
    16     result = self.target[self.index]
    17     self.index += 1
    18     return result
    19 
    20 
    21 class Skill:
    22   pass
    23 
    24 class SkillManager:
    25   def __init__(self):
    26     self.__list_skill = []
    27 
    28   def add_skill(self, skill):
    29     self.__list_skill.append(skill)
    30 
    31   def __iter__(self):
    32     return SkillIterator(self.__list_skill)
    33 
    34 
    35 manager = SkillManager()
    36 manager.add_skill(Skill())
    37 manager.add_skill(Skill())
    38 manager.add_skill(Skill())
    39 
    40 
    41 iterator = manager.__iter__()
    42 while True:
    43   try:
    44     item = iterator.__next__()
    45     print(item)
    46   except StopIteration:
    47     break
    迭代器1
     1 class Skill:
     2   pass
     3 
     4 
     5 class SkillManager:
     6   """
     7     可迭代对象
     8   """
     9 
    10   def __init__(self):
    11     self.__list_skill = []
    12 
    13   def add_skill(self, skill):
    14     self.__list_skill.append(skill)
    15 
    16   def __iter__(self):
    17     # return SkillIterator(self.__list_skill)
    18 
    19     for item in self.__list_skill:
    20       yield item
    21 
    22     """
    23       执行过程:
    24          1. 调用__iter__()方法程序不执行.
    25          2. 调用__next__()方法开始执行.
    26          3. 执行到yield语句暂时离开方法.
    27          4. 再次调用__next__()方法继续执行
    28          .....
    29       原理:如果方法体中包含yield语句,则自动生成迭代器代码.
    30       生成迭代器代码的大致规则:
    31         1.将yield关键字以前的代码,放到__next__()方法中.
    32         2.将yield关键字以后的数据,作为__next__()方法返回值.
    33     """
    34 
    35     # print("准备第一个元素:")
    36     # yield self.__list_skill[0]
    37     #
    38     # print("准备第二个元素:")
    39     # yield self.__list_skill[1]
    40     #
    41     # print("准备第三个元素:")
    42     # yield self.__list_skill[2]
    43 
    44 
    45 manager = SkillManager()
    46 manager.add_skill(Skill())
    47 manager.add_skill(Skill())
    48 manager.add_skill(Skill())
    49 
    50 
    51 iterator = manager.__iter__()
    52 while True:
    53   try:
    54     item = iterator.__next__()
    55     print(item)
    56   except StopIteration:
    57     break
    迭代器2
    1 tuple01 = (4, 4, 5, 565, 6, 7)
    2 iterator = tuple01.__iter__()
    3 while True:
    4   try:
    5     item = iterator.__next__()
    6     print(item)
    7   except:
    8     break
    练习1通过迭代器,获取元组元素.
    1 dict01 = {"张无忌":3,"赵敏":2}
    2 iterator = dict01.__iter__()
    3 while True:
    4   try:
    5     key = iterator.__next__()
    6     value = dict01[key]
    7     print(key,value)
    8   except:
    9     break
    练习2:{"张无忌":3,"赵敏":2} 通过迭代器,获取字典记录.

    生成器generator

    1.定义:能够动态(循环一次计算一次返回一次)提供数据的可迭代对象。

    2.作用:在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。

    3.以上作用也称之为延迟操作或惰性操作,通俗的讲就是在需要的时候才计算结果,而不是一次构建出所有结果。

    生成器函数

    1.定义:含有yield语句的函数,返回值为生成器对象。

    2.语法

    -- 创建:

    def 函数名():

    yield 数据

    -- 调用:

     for 变量名 in 函数名():

      语句

     1 class MyGenerator:
     2   """
     3     备注:本类是生成器的"源码",只需要看,不需要写.
     4     生成器:可迭代对象 + 迭代器对象
     5   """
     6 
     7   def __init__(self, stop_value):
     8     self.__stop_value = stop_value
     9     self.__start_value = 0
    10 
    11   def __iter__(self):
    12     return self
    13 
    14   def __next__(self):
    15     if self.__start_value >= self.__stop_value:
    16       raise StopIteration()
    17     result = self.__start_value
    18     self.__start_value += 1
    19     return result
    20 
    21 
    22 def my_range(stop_value):
    23   start_value = 0
    24   while start_value < stop_value:
    25     yield start_value
    26     start_value += 1
    27 
    28 
    29 # 0 1 2 3 4
    30 result = my_range(5)
    31 # 生成器对象.__iter__() 返回的结果就是生成器对象
    32 # 140573829693376
    33 print(id(result.__iter__()))
    34 # 140573829693376
    35 print(id(result))
    36 
    37 # 函数体包含yield语句,返回值类型是生成器.
    38 print(type(result))
    39 #<class 'generator'>
    40 for item in result:
    41   print(item)
    生成器

    3.说明:

    -- 调用生成器函数将返回一个生成器对象,不执行函数体。

    --  yield翻译为”产生”或”生成” 

    4.执行过程:

    (1) 调用生成器函数会自动创建迭代器对象。

    (2) 调用迭代器对象的__next__()方法时才执行生成器函数。

    (3) 每次执行到yield语句时返回数据,暂时离开。

    (4) 待下次调用__next__()方法时继续从离开处继续执行。

    5.原理:生成迭代器对象的大致规则如下

    -- 将yield关键字以前的代码放在next方法中。

    -- 将yield关键字后面的数据作为next方法的返回值。

     1 def get_even(list_target):
     2   for item in list_target:
     3     if item % 2 == 0:
     4       # return item  返回一个数据,退出方法.
     5       yield item  # 返回多个数据,暂时离开方法
     6 
     7 
     8 list01 = [34, 4, 54, 5, 7, 8]
     9 result = get_even(list01)
    10 # print(result)
    11 # 没有事先存储所有偶数,
    12 # 而是循环一次  计算一次  返回一次
    13 for item in result:
    14   print(item)
    练习3使用生成器函数,获取列表中所有偶数

    内置生成器

    枚举函数enumerate

    1.语法:

    for 变量 in enumerate(可迭代对象):

         语句

    for 索引, 元素in enumerate(可迭代对象):

        语句

    2.作用:遍历可迭代对象时,可以将索引与元素组合为一个元组。

    1 def my_enumerate(list_target):
    2   for i in range(len(list_target)):
    3     yield (i, list_target[i])
    4 
    5 for item in my_enumerate([3,34,4,5,6]):
    6   print(item)
    7 
    8 for index,item in enumerate([3,34,4,5,6]):
    9   print(index,item)
    练习

    zip

    1.语法:

    for item in zip(可迭代对象1, 可迭代对象2….):

         语句

    2.作用:将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。

     1 def my_zip(list01,list02):
     2   for i in range(len(list01)):
     3     yield (list01[i] ,list02[i])
     4 
     5 for item in my_zip([2,4,45],[5,6,8]):
     6   print(item)
     7 #(2, 5)
     8 #(4, 6)
     9 #(45, 8)
    10 list01 = ["张无忌","赵敏","周芷若"]
    11 list02 = [101,102]
    12 for item in zip(list01,list02,list02):
    13   print(item)
    14 #('张无忌', 101, 101)
    15 #('赵敏', 102, 102)
    练习

    生成器表达式

    1.定义:用推导式形式创建生成器对象。

    2.语法:变量 = ( 表达式 for 变量 in 可迭代对象 [if 真值表达式] )

    list01  = [4,4,5,56,6,78]
    # 立即执行,将所有结果存入内存
    result01 = [item for item in list01 if item >5]
    for item in result01:
      print(item)
    # 56 6 78
    result02 = (item for item in list01 if item >5)
    # 延迟执行,循环一次 计算一次  返回一个(覆盖了上一个)
    for item in result02:
      print(item)
    #56 6 78

    总结:

    (1)迭代器,生成器是什么?

    1.迭代器是一个更加抽象的概念,任何对象,如果他的类有next方法和iter方法返回自身.对于string,list,dict,tuple等这类容器对象,使用for循环遍历是很方便的.在后台for语句对容器对象调用了iter()函数,iter()是python的内置函数.iter()会返回一个定义了next()方法的迭代器对象,他在容器中逐个访问容器内元素,next()也是python的内置函数在没有后续元素时,next()会排除一个Stoplterration的异常.

    2.生成器是创建迭代器的简单而强大的工具,只是在返回数据的时候需要使用yield语句.每次next()被调用时,生成器就会返回他脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)

    (2)他们的区别?

    生成器一次只返回一个值,降低内存消耗,而迭代器一次返回所有值.

    生成器能做到迭代器能做的所有事,而且因为自动创建了 __ iter __ ()和next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存,除了创建和保持程序状态的自动生成,当生成器终结时,也会自动抛出Stoplterration的异常

  • 相关阅读:
    SpringBoot使用SpringSession和redis解决session共享问题(nginx反向代理)
    centos7中安装和配置nginx和keepalived
    定位
    css
    css美化
    html5
    列表,表格,媒体元素
    表单
    一期测试错题修改
    字符串
  • 原文地址:https://www.cnblogs.com/maplethefox/p/10909433.html
Copyright © 2011-2022 走看看