判断是否可迭代和是否迭代器
from collections import Iterable,Iterator
print(range(10000))
print(isinstance(range(10000),Iterable)) #是否可迭代
print(isinstance(range(10000),Iterator)) #是否可以变成迭代器
输出结果
range(0, 10000)
True
False
#python2 range 不管range多少 会生成一个列表,这个列表将用来存储所有的值
#python3 range 不管range多少 都不会实际的生成任何一个值
生成器 -- Generator
自己写的迭代器,就是生成器
两种自己写生成器(迭代器)的机制,生成器函数,生成器表达式
(1)生成器函数
def func():
print('****')
yield 1 #凡是带有yield的函数就是一个生成器函数
print('#####')
yield 2 #记录当前所在的位置,等待下一次next来触发函数的状态
g = func()
print('1111',next(g))
print('2222',next(g))
#生成器函数的调用不会触发代码的执行,而是会返回一个生成器(迭代器)
#想要生成器函数执行,需要用next
生成器函数的案例
def cloth_g(sum): #g表示生成器
for i in range(sum):
yield 'cloth %s'%i #凡是带有yield的函数就是一个生成器函数
g = cloth_g(100)
print(next(g))
print(next(g))
print(next(g))
结果
cloth 0
cloth 1
cloth 2
#使用生成器监听文件输入的例子
import time
def listen_file(): #生成器
with open('userinfo') as f: #1
while True: #2
line = f.readline() #3
if line.strip():
yield line.strip()
time.sleep(0.1)
g = listen_file()
for line in g:
print(line)
#send关键字
def func():
print(11111)
ret1 = yield 1
print(22222,'ret1 :' ,ret1)
ret2 = yield 2
print(33333,'ret2 :' ,ret2)
yield 3
g = func()
print(next(g))
print(g.send('alex')) #在执行next的过程中,传递一个参数,给生成器函数的内部
print(g.send('金老板'))
11111
1
22222 ret1 : alex
2
33333 ret2 : 金老板
3
#预激生成器
def init(func):
def inner(*args,**kwargs):
ret = func(*args,**kwargs)
next(ret) # 预激活
return ret
return inner
@init
def average():
sum_money = 0
day = 0
avg = 0
while True:
money = yield avg
sum_money += money
day += 1
avg = sum_money/day
g = average()
print(g.send(200))
print(g.send(300))
print(g.send(400))
#yield from
def gen_func():
# for i in range(5):
# yield i
# for j in 'hello':
# yield j
#或
yield from range(5)
yield from 'helle'
g = gen_func()
#第一种取值 #随时都可以停止,最后一次会报错
print(next(g))
#第二种取值 for 从头到尾不遇到break return不会停止
for i in g:
print(i)
#第三种取值 list或tuple 数据类型的强转,会把所有的数据都加载到内存里,非常的浪费内存
print(g)
print(list(g))
<generator object gen_func at 0x0000023F3F68EF68>
[0, 1, 2, 3, 4, 'h', 'e', 'l', 'l', 'o']
生成器总结函数:
# 生成器函数,是我们python程序员实现迭代器的一种手段
# 主要特征是载函数中,含有yield
# 调用一个生成器函数,不会调用这个函数中的代码,只是会获得一个生成器(迭代器)
# 只有从生成器中取值的时候,才会执行函数内部的代码,且每获取一个数据才执行得到这个数据的代码
# 获取数据的方式包括 next send 循环,数据类型的强制转化
# yield 返回值的简便方法,如果本身就是循环一个可迭代的,且要把可迭代数据中的每一个元素都返回,可以用yield from
# 使用send的时候,在生成器创造出来之后需要进行预激,这一步可以使用装饰器完成