迭代器(Iterator)和可迭代对象(Iterable)

2019年8月22日 / 19次阅读 / Last Modified 2019年9月3日
语法

Python的for循环语法上跟C语言差别较大,刚接触时我也很不适应,现在却觉得Python的for循环可读性非常好。迭代,就是在循环中遍历对象的所有元素,迭代的过程不一定都是for循环,while等其它循环方式也是在做迭代。

Python内置了的很多可迭代的数据对象,比如List,Dict,String,Tuple,Set等等。所谓可迭代对象(Iterable),简单说,就是可以直接在Python的for循环中遍历的对象。

下面的示例代码,将Python内置的各种常用可迭代对象,都做了一次遍历:

>>> a = [1,2,3,4,5]  # list
>>> for n in a: print(n)
...
1
2
3
4
5
>>> b = 'abcde'  # string
>>> for c in b: print(c)
...
a
b
c
d
e
>>> c = (1,2,3,4,5)  # tuple
>>> for n in c: print(n)
...
1
2
3
4
5
>>> d = {'a':1,'b':2,'c':3}  # dict
>>> for x in d: print(x)
...
a
b
c
>>> for k,v in d.items(): print(k,v)
...
a 1
b 2
c 3
>>> e = {1,2,3,4}  # set
>>> for i in e: print(i)
...
1
2
3
4

我们可以使用collections模块的Iterable对象来判断,某个对象是否是可迭代的。

>>> from collections.abc import Iterable
>>> isinstance('abcd', Iterable)
True
>>> isinstance((1,2,3,4), Iterable)
True
>>> isinstance(1234, Iterable)
False
>>> isinstance({}, Iterable)
True

可迭代对象不等于迭代器!但是,迭代器是一定是可迭代对象。Iterables are not equal to Iterators, but Iterators are all Iterables. 迭代器和可迭代对象的一个重要区别,就是能否用Python内置的next函数调用。迭代器可以,仅仅是可迭代对象不行。

>>> a = [1,2,3,4]
>>> next(a)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'list' object is not an iterator
>>> a = iter(a)
>>> next(a)
1
>>> next(a)
2
>>> next(a)
3
>>> next(a)
4
>>> next(a)
Traceback (most recent call last):
  File "", line 1, in 
StopIteration

a作为List对象,只是可迭代对象,不是迭代器,不能被next函数调用。用内置函数iter将a变为迭代器后,就可以使用next函数,一个一个将内部的数据释放出来使用,知道最后抛出StopIteration异常。

可迭代对象在遍历的时候,也是很方便的,为什么还要搞出一个迭代器出来?

我觉得是因为内存!

可迭代对象所有的数据都存放在内存中,而迭代器不全是这样。如果是生成器(generator,它也属于迭代器),在迭代过程中,数据一个个的释放出来,不会存在数据一次性释放出来而占用大量内存的情况。如果是可迭代对象转换而成的迭代器,每一个数据被释放出来后,对应的内存就消失,即只能next,而没有回头路可走。因此,迭代器在内存占用方面更友好。

下面用zip函数返回的迭代器来举例:

>>> zipped = zip('1234','abcd')
>>> list(zipped)
[('1', 'a'), ('2', 'b'), ('3', 'c'), ('4', 'd')]
>>> list(zipped)
[]  # data is gone for 2nd use
>>> zipped = zip('1234','abcd')
>>> next(zipped)
('1', 'a')
>>> next(zipped)
('2', 'b')
>>> next(zipped)
('3', 'c')
>>> next(zipped)
('4', 'd')
>>> next(zipped)
Traceback (most recent call last):
  File "", line 1, in 
StopIteration
>>> list(zipped)
[]  # no data at all

而如果只是一个可迭代对象,是可以反复迭代,数据不会被清除:

>>> a = [1,2,3,4]
>>> for i in a: print(i)
...
1
2
3
4
>>> for i in a: print(i)
...
1
2
3
4
>>> a
[1, 2, 3, 4]

这就是区别!最后说一下,迭代器可以使用next函数,迭代器也可以在for循环中迭代。

>>> zipped = zip('1234','abcd')
>>> for i in zipped:
...     print(i)
...
('1', 'a')
('2', 'b')
('3', 'c')
('4', 'd')
>>> for i in zipped:
...     print(i)
...

循环一次后,数据消失!

以上就是对Python中的可迭代对象(Iterable)和迭代器(Iterator)的介绍。

-- EOF --

本文链接:https://www.pynote.net/archives/939

留言区

电子邮件地址不会被公开。 必填项已用*标注


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top