一、迭代器
可迭代的(可迭代对象):
可迭代对象都是可迭代的。如:str、list、dict、tuple、文件对象等等
只要是对象有iter内部方法,就可以称之为可迭代对象
迭代器:
迭代器也是可迭代的,他不光有iter方法,还有next方法。
迭代器一次只能取一个值,直到取完后引发一个错误
获得一个迭代器:
调用可迭代对象的iter()就可以获得迭代器
使用迭代器:
调用迭代器的next()方法
使用for循环
迭代器的特点:
惰性运算
从前到后一次去取值,过程不可逆 不可重复
节省内存
如何判断一个变量是不是迭代器或者可迭代的
方法一:
print('iter' in dir([1,2,3,4]))
print('next' in dir([1,2,3,4]))
方法二:
from collections import Iterable
from collections import Iterator
print(isinstance([1,2,3,4],Iterable))
str_iter = 'abc'.iter()
print(isinstance(str_iter,Iterator))
print(isinstance('abc',Iterable))
二、生成器
生成器的本质就是迭代器,它有迭代器的所有特点,只不过生成器是自己编写的python 代码
1、生成器函数
生成器函数和普通函数之间的区别:
生成器函数中含有yield关键字
生成器函数调用的时候不会立即执行,而是返回一个生成器
def g_func():
print('aaaa')
yield 1
print('bbbb')
yield 2
yield 3
g = g_func()
for i in g:
print(i)
print(g.next())
print(g.next())
print(g.next())
def cloth():
for i in range(1000000):
yield '衣服%s'%i
g = cloth()
for i in range(50):
print(g.next())
for i in range(50):
print(g.next())
2、sned用法(进阶)
def func():
print(''10)
a = yield 5
print('a : ',a)
yield 10
g = func()
num = g.next()
print(num)
num2 = g.send('alex')
num2 = g.send('aaaa')
print(num2)
**在下面的例子中,send会在”yield average”处返回average,并将10传递到”yield average”处
**
def averager():
total = 0.0
count = 0
average = None
while True:
term = yield average
total += term
count += 1
average = total/count
g_avg = averager()
g_avg.next() ---》 先使用一次生成器,返回的值是None
print(g_avg.send(10)) ---》 传递的值是10,然后执行term =10,执行到第二次循环的yield average时候,返回average,这里打印的是第一次循环中的average = total/count计算出的值
print(g_avg.send(30)) ---》 从term = 处执行代码,然后把下一次循环的average返回,然后暂停
print(g_avg.send(20))
print(g_avg.send(100))
print(g_avg.send(200))
生成器的预激装饰器
在使用send的时候,需要先使用一次next方法,具体因素参照上面的例子
def init(func): #生成器的预激装饰器
def inner(args,kwargs):
g = func(args,**kwargs) #func = averager
g.next()
return g
return inner
@init
def averager():
total = 0.0
count = 0
average = None
term = yield average
total += term
count += 1
average = total/count
yield average
g_avg = averager()
print(g_avg.send(10))
print(g_avg.send(30))
3、总结
生成器函数:生成一个生成器的函数
生成器的本质参数迭代器
生成器函数的特点:
带有yield关键字
且调用之后,函数内的代码不执行
触发执行的方式:
next
send :send(None) == next(),send在next的基础上传一个值到生成器函数内部(send操作不能用在生成器使用的第一次)
for循环
网友评论