1 绪论
迭代是Python最强大的功能之一,是访问集合元素的一种方式。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。 迭代器有两个基本的方法:iter() 和 next()。
2 自定义迭代器
2.1 判断对象是否可迭代
isinstance
是一种判断对象类型的函数,和type
的功能差不多,但是使用的方法不同,具体的使用方法详见Python isinstance() 函数 | 菜鸟教程 使用isinstance(a, Iterable)
可以判断a
是否为可迭代,在使用Iterable
之前应该先导入:from collections import Iterable
,举个例子如下:
>> > a = [ 1 , 2 , 3 ]
>> > b = list
>> > c = { 1 : '1' , 2 : '2' , 3 : '3' }
>> > from collections import Iterable
>> > isinstance ( a, Iterable)
True
>> > isinstance ( b, Iterable)
False
>> > isinstance ( c, Iterable)
True
2.2 基于重写__getitem__
方法的自定义迭代器
这种方式并不常见,建议使用2.3中的方法 __getitem__
即利用索引获取值,用该方法书写迭代器的好处就是可以通过索引(即a[1]
这种形式)获取迭代器的值下面展示通过修改__getitem__
方法手写python的range
方法
class MyRange :
"""创建一个自己的Range函数"""
def __init__ ( self, minn, maxn= None , step= 1 ) :
"""初始化MyRange"""
self. minn, self. maxn = ( 0 , minn) if maxn is None else ( minn, maxn)
self. step = step
diff = self. maxn - self. minn
self. cnt = diff // step + ( 0 if diff % step == 0 else 1 )
self. cur = self. minn
def __getitem__ ( self, item) :
"""重写方法"""
if item < self. cnt:
return self. minn + ( item + self. cnt) % self. cnt * self. step
raise IndexError( '索引{}超出了范围{}' . format ( item, self. maxn) )
>> > for i in MyRange( 2 , 10 , 3 ) :
. . . print ( i, end= ' ' if i < 8 else '\n' )
. . .
2 5 8
>> > range ( 10 ) [ - 3 ]
7
>> > MyRange( 10 ) [ - 3 ]
7
2.3 基于重写__iter__
方法和__next__
方法的自定义迭代器
【注意】当类中没有__getitem__
方法时,上述的两种方法必须显式的定义在类中,才能使定义的类被识别为迭代对象。如果没有__getitem__
方法,这个类对象不能通过索引获取元素 。 __iter__
方法可以将需要的类返回作为迭代器类型逐次__next__
方法指定产生的返回结果 我们将上面的MyRange
类用__iter__
和__next__
实现:
在这里插入代码片
3 其他常用迭代器
3.1 iter
和next
在上文中介绍了如何使用__iter__
方法和__next__
方法自定义一个迭代器 iter
方法即调用对象的__iter__
方法,生成一个迭代器next
方法即调用对象的__next__
方法,将迭代器进行一次迭代,并返回对象的__next__
方法的返回值。如果对象中没有__next__
方法,则next
会调用对象的__getitem__
方法,并将参数item
的初始值设为0,返回__getitem__
方法的返回值
class MyRange2 :
"""创建一个自己的Range函数"""
def __init__ ( self, minn, maxn= None , step= 1 ) :
"""初始化MyRange"""
self. minn, self. maxn = ( 0 , minn) if maxn is None else ( minn, maxn)
self. step = step
diff = self. maxn - self. minn
self. cnt = diff // step + ( 0 if diff % step == 0 else 1 )
self. cur = self. minn
def __iter__ ( self) :
"""创建迭代器"""
return self
def __next__ ( self) :
"""返回下一元素"""
if self. cur < self. maxn:
self. cur += self. step
return self. cur - self. step
else :
raise StopIteration
for i in MyRange2( 2 , 10 , 3 ) :
print ( i, end= ' ' if i < 8 else '\n' )
2 5 8
print ( range ( 10 ) [ - 3 ] )
7
print ( MyRange2( 10 ) [ - 3 ] )
Traceback ( most recent call last) :
File "<input>" , line 1 , in < module>
TypeError: 'MyRange2' object is not subscriptable
3.2 zip
同时去除多个对象中索引相同的元素
zip()
函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。我们可以使用 list() 转换来输出列表。 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同 利用 * 号操作符,可以将元组解压为列表,即zip(*)
可以理解为解压
>> > a = [ 1 , 2 , 3 ]
>> > b = [ 4 , 5 , 6 ]
>> > c = [ 4 , 5 , 6 , 7 , 8 ]
>> > zipped = zip ( a, b)
>> > zipped
< zip object at 0x103abc288 >
>> > list ( zipped)
[ ( 1 , 4 ) , ( 2 , 5 ) , ( 3 , 6 ) ]
>> > list ( zip ( a, c) )
[ ( 1 , 4 ) , ( 2 , 5 ) , ( 3 , 6 ) ]
>> > a1, a2 = zip ( * zip ( a, b) )
>> > list ( a1)
[ 1 , 2 , 3 ]
>> > list ( a2)
[ 4 , 5 , 6 ]
>> >