防伪码:忘情公子著
何为迭代?迭代就是重复做一件事
可迭代(iterable)对象有哪些:
支持每次返回自己所包含的一个成员的对象;
对象在内部实现了__iter__方法或者__getitem__方法:
序列类型,如:list、str、tuple
非序列类型,如:dict、file
用户自定义的一些包含了__iter__()或__getitem__()方法的类
可以直接作用于for循环的数据有以下几种:
1、集合数据类型:list、tuple、dict、file、str等
2、生成器对象:generator,包括生成器和带yield的generator function
这些可直接作用于for循环的对象统称为可迭代对象:Iterable
可以使用isinstance()判断一个对象是否是Iterable对象。In [3]: from collections import Iterable
In [4]: isinstance([],Iterable)
Out[4]: True
In [5]: isinstance('abc',Iterable)
Out[5]: True
可迭代对象能干什么?
可迭代对象支持每次返回自己所包含的一个成员的对象,每次取得一个,从头遍历到尾部。也就是说可迭代对象本身是可遍历的。
以下举例来说明:
定义一个列表:list1 = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
使用dir()函数查看list1列表所支持的所有方法和属性In [2]: dir(list1)
Out[2]:
['__add__',
'__class__',
'__contains__',
'__delattr__',
'__delitem__',
'__delslice__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__getitem__',
'__getslice__',
'__gt__',
'__hash__',
'__iadd__',
'__imul__',
'__init__',
'__iter__',
'__le__',
'__len__',
'__lt__',
'__mul__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__reversed__',
'__rmul__',
'__setattr__',
'__setitem__',
'__setslice__',
'__sizeof__',
'__str__',
'__subclasshook__',
'append',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']
在输出中可以看到list1的方法中有__iter__和__getitem__。
list1.__iter__()方法返回一个可迭代对象的迭代器地址,而不是返回元素本身,这就意味着,当调用__iter__方法或者__getitem__方法时,在内存中就创建了一个能够遍历某个对象的每一个元素的迭代器In [3]: list1.__iter__()
Out[3]:
一直在说迭代器,那么到底什么是迭代器呢?
迭代器(iterator)又称游标(cursor),它是程序设计的软件设计模式,是一种可以在容器物件(container,如列表等)上实现元素遍历的接口。迭代器是一种特殊的数据结构,它是以对象的形式存在的。
说白点,可以被next()函数调用并不断返回下一个值的对象称之为迭代器:Iterator
对于集体中每一个元素,想要执行遍历,那么针对这个集体的迭代器定义了遍历集体中每一个元素的顺序或者方法。对于迭代器来说,我们可以对它调用next方法来获取其每一个元素或者说遍历其每一个元素。
迭代器是不可逆的,当遍历结束后抛出异常,不会从头开始再次迭代,若想从头再来一遍只能重新创建一个迭代器
除了调用__iter__和__getitem__方法能生成一个迭代器以外,还可以调用iter()函数来生成迭代器,其方法是:
iter(可迭代对象),如:In [4]: iter(list1)
Out[4]:
iter(list1)相当于调用了list1的__iter__方法
生成器是迭代器对象,但list、tuple、dict、str虽然是可以迭代对象,却不是迭代器对象,因为他们都没有next()方法。
我们可以用iter()函数将list、tuple、dict、str等转换成迭代器。
既然我们可以通过iter()函数将list、tuple、dict、str等这些数据类型转换成迭代器,那为什么不一开始就让这些数据类型默认就是一个迭代器对象呢?
这是因为python中的Iterator迭代器对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration异常。
我们可以把这个数据流看成是一个有序的序列,但我们不可能知道这个序列的准确长度,只能通过next()函数不断的按需生成下一个数据,所以Iterator的计算是惰性的。
在python中,迭代器是遵循迭代协议的对象,使用iter()可从任何序列对象中得到迭代器,若要实现迭代器,需要在类中定义next()方法(python3中是__next__())
要使得迭代器指向下一个元素,则使用成员函数next():
在python中,是函数next(),而非成员函数
当没有元素时,则引发StopIteration异常。In [5]: a = iter(list1)
In [6]: a.next()
Out[6]: 'Sun'
In [7]: a.next()
Out[7]: 'Mon'
In [8]: a.next()
Out[8]: 'Tue'
In [9]: a.next()
Out[9]: 'Wed'
In [10]: a.next()
Out[10]: 'Thu'
In [11]: a.next()
Out[11]: 'Fri'
In [12]: a.next()
Out[12]: 'Sat'
In [13]: a.next()
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
in ()
----> 1 a.next()
StopIteration:
for循环可用于任何可迭代对象:
for循环开始时,会通过迭代协议传递给iter()内置函数,从而能够从可迭代对象中获得一个迭代器,返回的对象有需要的next方法。