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的异常

 

posted @ 2019-05-23 23:38  maplethefox  阅读(474)  评论(0编辑  收藏  举报