[ Python ] 迭代对象、迭代器、生成器

1. 容器(container)

容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个的迭代获取,可以用 in / not in 关键字判断元素是否包含在容器中。通常这类数据结构把所有元素存储在内存中。比如:list, set, tuples都是容器对象

>>> 1 in [1, 2, 3]
True
>>> 4 not in [1,2,3]
True
>>> 1 in (1,2,3)
True
>>> 4 not in (1,2,3)
True
>>> 1 in {1,2,3}
True
>>> 4 not in {1,2,3}
True

2. 可迭代对象(iterable)

什么的迭代?
    迭代就是可以被 for 循环遍历, 在python中一切皆对象,可以被 for 循环迭代的对象就叫 可迭代对象;

>>> for i in [1,2,3]:
...     print(i)
...
1
2
3
>>> for i in (1,2,3):
...     print(i)
...
1
2
3
>>> for i in {'a': 1, 'b': 2, 'c': 3}:
...     print(i)
...
a
c
b

 可迭代对象并不是指某种具体的数据类型,list 是可迭代对象,dict是可迭代对象,set也是可迭代对象。

3. 迭代器(iterator)

可迭代对象是实现了 __iter__() 方法的对象,而迭代器(iterator)则是实现了 __iter__() 和 __next()__ 方法的对象,可以显示的获取下一个元素,这种可以被 next 调用并不断返回下一个值的对象称为迭代器;

iterator是一个带状态的对象,能在调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()方法的对象都是迭代器
__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多的元素了,则抛出StopIteration异常。所以迭代器是每次询问要下一个值的时候返回

迭代器一定是可迭代对象,反过来则不一定成立。

>>> l1 = ['a', 'b', 'c']
>>> l_iter = l1.__iter__()
# 可迭代对象通过调用 __iter__方法生成一个迭代器
>>> l_iter
<list_iterator object at 0x000001EA16975710>
# 迭代器通过 __next__方法返回一个值
>>> l_iter.__next__()
'a'
>>> l_iter.__next__()
'b'
>>> l_iter.__next__()
'c'
>>> l_iter.__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

 迭代器是一个惰性的计算,等到有人调用的时候才返回值,没调用的时候就处于休眠状态等待下一次调用。

4. 生成器(generator)

generator 是一种数据类型,这种数据类型自动实现了迭代器协议,所以生成器就是可迭代对象;
生成器一定是迭代器,反之则不成立。
当在内存中存储一个很大的列表时,需要消耗大量的内存,如果列表元素可以按照某种算法推算出来,那我们就可以通过循环的过程不断推算出后续的元素,这样就不必创建完成的list, 从而节约了大量的空间。在python中,这种一边循环一边计算的机制,称为生成器(generator)

创建一个生成器有两种方式:

(1)把一个列表生成式的[]改成()

>>> l1 = ['a', 'b', 'c']
>>> l = [x for x in range(10)]
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> g = (x for x in range(10))
>>> g
<generator object <genexpr> at 0x000001EA16972308>	

 
(2)通过yield 关键字

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n += 1


f = fib(5)
print(list(f))

# 执行结果:
# [1, 1, 2, 3, 5]

fib就是一个普通的python函数,特殊的地方在于函数体中没有 return关键字,函数的返回值是一个生成器对象。此时函数体中的代码并不会执行,保存的是一个算法。
可以通过遍历迭代器的方式来遍历生成器。

5. 总结

 (1)容器是一系列元素的集合:str, list, set, dict, file, sockets对象都可以看做容器,容器是可以被迭代的,因此他们称为可迭代对象
    (2)可迭代对象实现了__iter__方法,该方法返回一个迭代器对象
    (3)迭代器持有一个内部状态的字段,用于记录下一次迭代返回值,它实现了__next__和__iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候返回结果。
    (4)生成器是一种特殊的迭代器,它的返回值不是通过return而是通过yield.

猜你喜欢

转载自www.cnblogs.com/hukey/p/9254950.html
今日推荐