可迭代对象(iterable)
简介
凡是可作用于
for...in...
循环的对象都是 Iterable 类型:一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
一类是 generator ,包括生成器和带 yield 的generator function。 这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable
可以使用 isinstance() 判断一个对象是否是 Iterable 对象
from collections import Iterable
simple_list = [1, 2, 3, 4, 5]
simple_dict = {'name': 'Tom', 'age': 20}
print(isinstance(simple_list, Iterable)) # True
print(isinstance(simple_dict, Iterable)) # True
迭代器(iterator)
简介
- 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
- 生成器都是 Iterator 对象,集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象
- 迭代器对象可以使用常规for语句进行遍历
- 迭代器对象一定是可迭代对象,Iterator继承于Iterable
- 优点:
- 省内存:迭代器不需要事先准备好整个迭代过程中的所有元素,仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或销毁。这也是迭代器的一大优点:适合用于遍历一个巨大的或无限的集合。
from collections import Iterator
simple_list = [1, 2, 3, 4, 5]
simple_dict = {'name': 'Tom', 'age': 20}
print(isinstance(simple_list, Iterator)) # False
print(isinstance(simple_dict, Iterator)) # False
my_iter = iter(simple_list)
print(isinstance(my_iter, Iterator)) # True
遍历迭代器
- 方式一:for…in…
simple_list = [1, 2, 3, 4, 5]
it = iter(simple_list)
for i in it:
print(i)
- 方式二:next(),返回迭代器的下一个项目
import sys
simple_list = [1, 2, 3, 4, 5]
it = iter(simple_list)
while True:
try:
print(next(it))
except:
sys.exit()
自定义迭代器
__iter__()
方法:返回迭代器对象本身;__next__()
方法:返回容器中的下一个元素,在结尾时引发StopIteration异常终止迭代器。
from collections import Iterator
class MyIterator:
def __init__(self, max):
self.max = max
self.id = 0
def __next__(self):
if self.id < self.max:
self.id += 1
return self.id
else:
raise StopIteration('没有元素')
def __iter__(self):
return self
my_iterator = MyIterator(5)
print('是否是迭代器:', isinstance(my_iterator, Iterator))
for item in my_iterator:
print(item)
输出信息:
是否是迭代器: True
1
2
3
4
5
自定义可迭代对象
from collections import Iterator
from collections import Iterable
# 迭代器对象
class MyIterator:
def __init__(self, arrs):
self.index = 0
self.arrs = arrs
def __next__(self):
if self.index > len(self.arrs) - 1:
raise StopIteration
else:
self.index += 1
return self.arrs[self.index - 1]
def __iter__(self):
return self
# 可迭代对象
class MyIterable:
def __init__(self, arrs):
self.arrs = arrs
def __iter__(self):
return MyIterator(self.arrs)
my_iterable = MyIterable([1, 2, 3, 4, 5, 6])
print('是否是可迭代对象', isinstance(my_iterable, Iterator))
print('是否是迭代器', isinstance(my_iterable, Iterable))
for item in my_iterable:
print(item)
输出信息:
是否是可迭代对象 False
是否是迭代器 True
1
2
3
4
5
6
可迭代对象和迭代器总结
- 可以用for循环遍历的对象统称为可迭代对象(Iterable),其内部实现
__iter__()
方法 - 可以被next()函数调用,不断返回下一个值的对象被成为迭代器(Iterator),其内部实现
__iter__()
和__next__()
方法 - 迭代器继承于可迭代对象
from collections import Iterable, Iterator
class MyIterable:
def __iter__(self):
pass
class MyIterator:
def __iter__(self):
pass
def __next__(self):
pass
my_iterable = MyIterable()
my_iterator = MyIterator()
print(isinstance(my_iterable, Iterable))
print(isinstance(my_iterable, Iterator))
print(isinstance(my_iterator, Iterable))
print(isinstance(my_iterator, Iterator))
输出信息:
True
False
True
True
生成器(generator)
简介
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()
和__next__()
方法了,只需要一个yiled
关键字。 生成器一定是迭代器。
from collections import Iterator
simple_list = [x for x in range(5)]
simple_tuple = (x for x in range(5))
print(isinstance(simple_list, Iterator))
print(isinstance(simple_tuple, Iterator))
输出信息:
False
True
生成器函数
定义一个生成器函数
def fib(n):
a, b, count = 0, 1, 0
while count < n:
yield b
a, b = b, a + b
count += 1
遍历方式一:for…in…
f = fib(10)
for i in f:
print(i, end=' ')
输出信息:
1 1 2 3 5 8 13 21 34 55
遍历方式二:next()
f = fib(10)
while True:
try:
x = next(f)
print(x, end=' ')
except StopIteration as e:
break
输出信息:
1 1 2 3 5 8 13 21 34 55
遍历方式三:send()
send是传递值给yield表达式
def func():
n = 0
while True:
y = yield n
print(y)
n += 1
# 使用send调用生成器
f = func()
t = f.send(None)
print(t)
x = f.send('value')
print(x)
x = f.send('value2')
print(x)
输出信息:
0
value
1
value2
2
执行顺序:先返回0 -> 再输出value -> 在返回1 -> 再输出value2 -> 再返回2
和next用法比较类似
使用send生成斐波拉契数列
def fib(n):
a, b, count = 0, 1, 0
while count < n:
t = yield b
print(t)
a, b = b, a + b
count += 1
# 使用send调用生成器
t = fib(5)
temp = t.__next__()
print(temp)
while True:
try:
x = t.send('传值')
print('value=%s' % x)
except StopIteration as e:
# print('value=%s' % e.value)
break
输出信息:
1
传值
value=1
传值
value=2
传值
value=3
传值
value=5
传值
可迭代对象,迭代器,生成器,列表之前的差异
对象 | 是否可迭代 | 是否迭代器 |
---|---|---|
可迭代对象 | ✔ | ❓ |
迭代器 | ✔ | ✔ |
生成器 | ✔ | ✔ |
列表 | ✔ | ✖ |
- 容器是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象。
- 可迭代对象实现了__iter__
方法,该方法返回一个迭代器对象。
- 迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next__
和__iter__
方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
- 生成器是一种特殊的迭代器,它的返回值不是通过return
而是用yield
。