Python之路——迭代器与生成器

Posted liuyankui163

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python之路——迭代器与生成器相关的知识,希望对你有一定的参考价值。

一、迭代器

技术分享图片
  1 # -*- encoding:utf-8 -*-
  2 
  3 
  4 # dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法
  5 # print(dir([1,2].__iter__()))
  6 # print(dir([1,2]))
  7 # print(set(dir([1,2].__iter__()))-set(dir([1,2])))   # {‘__length_hint__‘, ‘__setstate__‘, ‘__next__‘}
  8 
  9 # iter = [1,2,3,4,5,6].__iter__()
 10 # print(iter.__length_hint__())
 11 # print(iter.__next__())
 12 # print(iter.__next__())
 13 # print(iter.__length_hint__())   # 获取迭代器中剩余元素的长度
 14 #
 15 # print(‘**‘,iter.__setstate__(0))    # 根据索引值指定从哪里开始迭代
 16 # print(iter.__next__())
 17 # print(iter.__next__())  # 一个一个的取值
 18 # print(iter.__next__())
 19 # print(iter.__next__())
 20 
 21 # l = [1,2,3,5]
 22 # l_iter = l.__iter__()
 23 # item = l_iter.__next__()
 24 # print(item)
 25 # item = l_iter.__next__()
 26 # print(item)
 27 # item = l_iter.__next__()
 28 # print(item)
 29 # item = l_iter.__next__()
 30 # print(item)
 31 # item = l_iter.__next__()    # 如果迭代器里已经没有元素了,会抛出一个StopIteration异常
 32 # print(item)
 33 
 34 # l = [1,2,3,4]
 35 # l2 = l.__iter__()
 36 # while True:
 37 #     try:
 38 #         item = l2.__next__()
 39 #         print(item)
 40 #     except StopIteration:
 41 #         print(‘迭代完毕‘)
 42 #         break
 43 
 44 # 迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法
 45 
 46 # range()
 47 # print(‘__next__‘ in dir(range(12))) # False
 48 # print(‘__iter__‘ in dir(range(12))) # True
 49 
 50 # from collections import Iterator
 51 # print(isinstance(range(12),Iterator))   # False , 验证range执行之后得到的结果不是一个迭代器
 52 
 53 # 为何要有for循环
 54 
 55 # l = [1,2,3]
 56 # index = 0
 57 # while index < len(l):
 58 #     print(l[index])
 59 #     index += 1
 60 
 61 # 序列类型字符串,列表,元组都有下标,用上述方式访问,perfect!
 62 # 但是对于字典、集合、文件对象这种非序列型类型,就得使用for循环了。
 63 # for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,
 64 # 即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,
 65 # 然后使用迭代器去循环访问
 66 
 67 # 迭代器的好处是可以节省内存
 68 
 69 # print(‘__iter__‘ in dir(int))   # False
 70 # print(‘__iter__‘ in dir(bool))  # False
 71 # print(‘__iter__‘ in dir(list))  # True
 72 # print(‘__iter__‘ in dir(dict))  # True
 73 # print(‘__iter__‘ in dir(set))   # True
 74 # print(‘__iter__‘ in dir(tuple)) # True
 75 # print(‘__iter__‘ in dir(enumerate([]))) # True
 76 # print(‘__iter__‘ in dir(range(2))) # True
 77 # print(‘__next__‘ in dir(range(2))) # False
 78 # print(‘__next__‘ in dir(dict))  # False
 79 
 80 # g = range(10).__iter__()
 81 # print(g.__next__())
 82 # print(g.__next__())
 83 # print(g.__next__())
 84 # print(g.__next__())
 85 # print(g.__next__())
 86 # print(g.__next__())
 87 from collections import Iterator
 88 from collections import Iterable
 89 
 90 # class A:
 91 #     def __iter__(self): pass
 92 #     def __next__(self): pass
 93 #
 94 # a = A()
 95 # print(isinstance(a,Iterator))   # True
 96 # print(isinstance(a,Iterable))   # True
 97 
 98 # class A:
 99 #     def __iter__(self): pass
100 #     #def __next__(self): pass
101 #
102 # a = A()
103 # print(isinstance(a,Iterator))   # False
104 # print(isinstance(a,Iterable))   # True    含有__iter__方法,是可迭代的,可迭代的,不一定是迭代器
105 
106 # class A:
107 #     # def __iter__(self): pass
108 #     def __next__(self): pass
109 #
110 # a = A()
111 # print(isinstance(a,Iterator))   # False
112 # print(isinstance(a,Iterable))   # False   不含有__iter__方法,是不可迭代的
113 
114 # 可以被for循环的都是可迭代的
115 # 可迭代的内部都有__iter__方法
116 # 只要是迭代器,一定可迭代
117 # print(range(10).__iter__())
118 
119 # for
120 # 只有可迭代对象才能用for
121 # b = [].__iter__()
122 # a = b.__iter__()
123 # c = [].__iter__().__iter__()
124 # print(b)
125 # print(a)
126 # print(c)
View Code

二、生成器

技术分享图片
# -*- encoding:utf-8 -*-

# 在某些情况下,我们想要像迭代器那样节省内存,就只能自己写。
# 我们自己写的这个能实现迭代器功能的东西就叫生成器

# Python中提供的生成器:
# 1.生成器函数:常规函数定义,但是使用yield语句返回结果,而不是return语句。
#   yield语句一次返回一个结果,在那个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
# 2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
# yield 和return不能共用

# 初识生成器
# import time
# def generator_fun1():
#     a = 1
#     print(‘现在定义了a变量‘)
#     yield a
#     b = 2
#     print(‘现在定义了b变量‘)
#     yield b
#
# g1 = generator_fun1()   # generator_fun1() 返回一个可迭代的对象
# print(‘g1: ‘,g1)    # g1: <generator object generator_fun1 at 0x00000250C7EBE4C0>
#
# print(next(g1))
# time.sleep(1)
# print(next(g1))
# 输出:
# 现在定义了a变量
# 1
# 现在定义了b变量
# 2

# 生成器好处:不会一下子在内存中生成太多数据


# 初识生成器二
# def produce():
#     ‘‘‘生成衣服‘‘‘
#     for i in range(1,200):
#         yield ‘生成了第%s件衣服‘%i
#
# product_g = produce()
# print(product_g.__next__())
# print(product_g.__next__())
# print(product_g.__next__())
# num = 0
# for i in product_g:
#     print(i)
#     num += 1
#     if num == 5:
#         break

# 生成器监听文件输入????????????????????
# import time
# def tail(filename):
#     f = open(filename,encoding=‘utf-8‘)
#     f.seek(0,2) # 从文件末尾算起
#     while 1:
#         line = f.readline() # 读取文件中新的文本行
#         if not line.strip():
#             time.sleep(0.1)
#             continue
#         yield line.strip()
# tail_g = tail(‘tmp‘)
# for line in tail_g:
#     print(line)

# import time
# def tail(filename):
#     f = open(filename,encoding=‘utf-8‘)
#     f.seek(0,2)
#     while 1:
#         line = f.readline().strip()
#         if not line:
#             time.sleep(0.1)
#             continue
#         yield line
# tail_g = tail(‘tmp‘)
# for line in tail_g:
#     print(line)

# 计算移动平均值
# def averager():
#     total = 0.0
#     count = 0
#     average = None
#     while True:
#         term = yield average
#         total += term
#         count += 1
#         average = total/count
#
# g_avg = averager()
# next(g_avg)
# print(g_avg.send(10))# 先send一个值,再执行next函数
# print(g_avg.send(30))
# print(g_avg.send(50))

# 计算移动平均值二
# def init(func):
#     def inner(*args,**kwargs):
#         g = func(*args,**kwargs)
#         next(g)
#         return g
#     return inner
# @init
# def averager():
#     total = 0.0
#     count = 0
#     average = None
#     while True:
#         term = yield average
#         total += term
#         count += 1
#         average = total/count
#
#
# g_avg = averager()
#
# print(g_avg.send(10))
# print(g_avg.send(30))
# print(g_avg.send(50))

# yield from
# def gen1():
#     for c in "AB":
#         yield c
#     for i in range(3):
#         yield i
# print(list(gen1())) # [‘A‘, ‘B‘, 0, 1, 2]
#
# def gen2():
#     yield from ‘AB‘
#     yield from range(3)
# print(list(gen2())) # [‘A‘, ‘B‘, 0, 1, 2]

#列表推导式和生成器表达式
# egg_list = [‘鸡蛋%s‘ %i for i in range(10)] # 列表解析
# print(egg_list)
#
# laomuji = (‘鸡蛋%s‘ %i for i in range(10)) # 生成器表达式
# print(laomuji)
# print(next(laomuji))    # next()本质就是调用__next__
# print(laomuji.__next__())
# print(next(laomuji))

#总结
# 1.把列表解析的[]换成()得到的就是生成器表达式
# 2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
# 3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议
#   访问对象的。例如,sun函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器的协议,
#   所以,我们可以直接这样计算一系列值的和:
# print(sum(x ** 2 for x in range(4)))
View Code

三、生成器进阶练习

技术分享图片
  1 # -*- encoding:utf-8 -*-
  2 # def generator():
  3 #     print(123)
  4 #     content = yield 1
  5 #     print(‘=====‘,content)
  6 #     print(456)
  7 #     arg = yield 2
  8 #     print(arg)
  9 #     yield
 10 
 11 # g1 = generator()
 12 # g2 = generator()
 13 # g1.__next__()
 14 # g2.__next__()
 15 # print(‘***‘,generator().__next__())
 16 # print(‘***‘,generator().__next__())
 17 
 18 # g = generator()
 19 # ret = g.__next__()
 20 # print(ret)
 21 # ret = g.send(‘hello‘)
 22 # print(ret)
 23 # print(g.send(1234))
 24 
 25 # send 获取下一个值的效果和next基本一致
 26 # 只是在获取下一个值的时候,给上一个yield的位置传递一个数据
 27 #使用send的注意事项
 28     # 第一次使用生成器的时候,是用next获取下一个值
 29     # 最后一个yield不能接受外部的值
 30 
 31 # def init(func):
 32 #     def inner(*args,**kwargs):
 33 #         g = func(*args,**kwargs)
 34 #         g.__next__()
 35 #         return g
 36 #     return inner
 37 # @init
 38 # def averager():
 39 #     sum = 0.0
 40 #     count = 0
 41 #     average = 0
 42 #     while 1:
 43 #         temp = yield average
 44 #         sum += temp
 45 #         count += 1
 46 #         average = sum/count
 47 # g = averager()
 48 # print(g.send(10))
 49 # print(g.send(30))
 50 # print(g.send(5))
 51 
 52 #yield from
 53 # def gnrator():
 54 #     a = ‘AB‘
 55 #     for i in a:
 56 #         yield i
 57 #     b = [1,2,3]
 58 #     for i in b:
 59 #         yield i
 60 # g = gnrator()
 61 # for i in g:
 62 #     print(i)
 63 
 64 # def gnrator2():
 65 #     yield from ‘AB‘
 66 #     yield from [1,2,3]
 67 # g = gnrator2()
 68 # for i in g:
 69 #     print(i)
 70 
 71 # 列表推导式
 72 # egg_list = [‘egg%s‘ %i for i in range(10)]
 73 # print(egg_list)
 74 # print([i*i for i in range(1,10)])
 75 
 76 # 生成器表达式
 77 # g = (i for i in range(10)) #几乎不占用内存
 78 # print(g)
 79 # for i in g:
 80 #     print(i)
 81 
 82 # g2 = (i for i in range(20) if i%2 == 1)
 83 # for i in g2:
 84 #     print(i)
 85 
 86 # g3 = (i*i for i in range(10))
 87 # for i in range(10):
 88 #     print(g3.__next__())
 89 
 90 #各种推导式练习
 91 # names = [[‘Tom‘, ‘Billy‘, ‘Jefferson‘, ‘Andrew‘, ‘Wesley‘, ‘Steven‘, ‘Joe‘],
 92 #          [‘Alice‘, ‘Jill‘, ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘, ‘Eva‘]]
 93 # ret = [name for lst in names for name in lst if name.count(‘e‘) == 2]
 94 # print(ret)
 95 # 字典推导式
 96 # mcase = {‘a‘: 10, ‘b‘: 34, ‘A‘: 7, ‘Z‘: 3}
 97 # mcase2 = {k.lower(): mcase.get(k.lower(),0)+mcase.get(k.upper(),0) for k in mcase}
 98 # print(mcase2)
 99 # 集合推导式
100 # sq = {x**2 for x in [1,-1,2]}
101 # print(sq)
View Code

 

以上是关于Python之路——迭代器与生成器的主要内容,如果未能解决你的问题,请参考以下文章

Python之路——迭代器与生成器

Python高手之路python基础之迭代器与生成器

[js高手之路] es6系列教程 - 迭代器与生成器详解

python-迭代器与生成器1

Python3 迭代器与生成器

python 基础篇 13 迭代器与生成器