迭代器&生成器
一、可迭代的&迭代器
可迭代协议
①协议内容:内部实现了__iter__方法
②验证方法:dir()方法;使用dir()方法查看数据类型中的方法是否包含__iter__
③__iter__()方法的作用:可迭代的数据类型执行__iter__()方法后会生成一个迭代器对象
④例子:
print([1,2].__iter__())
0x1024784a8>
迭代器协议
①迭代器的引出
"""
dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,
都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,然后取差集。
"""
print(set(dir([1,2].__iter__()))-set(dir([1,2])))
结果:
{'__length_hint__', '__next__', '__setstate__'}
iter_l = [1,2,3,4,5,6].__iter__()
print(iter_l.__length_hint__())
print('*',iter_l.__setstate__(4))
print('**',iter_l.__next__())
print('***',iter_l.__next__())
②协议内容:必须拥有__iter__方法和__next__方法
二、生成器
①种类:python中提供的生成器有:
- 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
- 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
②本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
③特点:惰性运算,开发者自定义
④生成器函数:一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
import time
def genrator_fun1():
a = 1
print('现在定义了a变量')
yield a
b = 2
print('现在又定义了b变量')
yield b
g1 = genrator_fun1()
print('g1 : ',g1)
print('-'*20)
print(next(g1))
time.sleep(1)
print(next(g1))
- 2) 生成器函数的好处:可以避免一次性读取数据到内存中导致内存溢出
def produce():
"""生产衣服"""
for i in range(2000000):
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)
f.seek(0, 2)
while True:
line = f.readline()
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))
print(g_avg.send(30))
print(g_avg.send(5))
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(5))
def gen1():
for c in 'AB':
yield c
for i in range(3):
yield i
print(list(gen1()))
以上是将生成器中的数据以列表的方式打印
以下的执行效果与上面相同,运用了yield from 语法
def gen2():
yield from 'AB'
yield from range(3)
print(list(gen2()))
⑤生成器函数进阶
send():
- send和next的作用相同
- 第一次不能用send
- 函数中的最后一个yield不能接受新的值
def average():
sum = 0
count = 0
avg = 0
while True:
num = yield avg
sum += num
count += 1
avg = sum / count
avg_g = average()
avg_g.__next__()
print(avg_g.send(20))
print(avg_g.send(40))
print(avg_g.send(60))
def init(func):
def wrapper(*args,**kwargs):
g = func(*args,**kwargs)
g.__next__()
return g
return wrapper
@init
def average():
sum,avg,count = 0,0,0
while True:
num = yield avg
sum += num
count += 1
avg = sum/count
avg_g = average()
print(avg_g.send(10))
print(avg_g.send(20))
print(avg_g.send(30))
⑥生成器表达式
'''
列表推导(列表生成式)
'''
l = [i ** 2 for i in range(10)]
print(l)
'''
生成器表达式
与列表推导相似,返回生成器对象
'''
g = (i ** 2 for i in range(10))
print(g.__next__())
for i in g:
print(i)
print(list(g))
⑦各种推导式
'''
列表推导
[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理
[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能
'''
l = [i ** 3 for i in range(10)]
print(l)
>>> [0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
l = [i ** 3 for i in range(10) if i % 3 == 0]
print(l)
>>> [0, 27, 216, 729]
double_l = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
l = [name for lst in double_l for name in lst if name.count('e') >= 2]
print(l)
>>> ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
'''
字典推导
'''
mcase = {'a': 10, 'b': 34}
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)
>>> {34: 'b', 10: 'a'}
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
print(mcase_frequency)
>>> {'b': 34, 'a': 17, 'z': 3}
'''
集合推导
'''
squared = {x ** 2 for x in [1, -1, 2]}
print(squared)
>>> {1, 4}
'''
练习题
'''
lst = ['123', 'ab', 'y', 'abcabc', 'okiuj']
l = [i.upper() for i in lst if len(i) > 3]
print(l)
>>> ['ABCABC', 'OKIUJ']
lst = [(4, 3), (3, 2), (8, 1), (8, 6)]
t = [i for i in lst if ((i[0] % 2 == 0) and (i[1] % 2 != 0))]
print(t)
>>> [(4, 3), (8, 1)]
M = [[1,2,3],[4,5,6],[7,8,9]]
l = [i[2] for i in M]
print(l)
>>> [3, 6, 9]