在Python中,经过使用for...in...语句进行循环的对象,就是可迭代对象(Iterable)。一般使用isinstance来进行判断。python
In [4]: from collections import Iterable In [5]: for i in "Python": ...: print(i) ...: P y t h o n In [7]: a = [100,200,300] In [8]: for i in a: ...: print(i) ...: 100 200 300
经过isinstance()来看,返回都是Truessh
In [13]: from collections import Iterable In [11]: isinstance("python",Iterable) Out[11]: True In [12]: isinstance(a,Iterable) Out[12]: True
下面看一个不是可迭代对象的例子:ide
In [13]: b =200 In [14]: for i in b: ...: print(i) ...: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-14-5049783fdcea> in <module>() ----> 1 for i in b: 2 print(i) 3 TypeError: 'int' object is not iterable In [15]: isinstance(b,Iterable) Out[15]: False
看报错说明,整型并非一个可迭代对象。经过isinstance()看返回False。
经过dir()查看发现可迭代对象都有__iter__
方法。
总结:含有__iter__
方法的对象都是可迭代对象。函数
迭代器是指能够使用next()方法来进行回调的对象,能够经过使用iter()方法,将一个可迭代对象转换成迭代器。在next()方法进行调用时,若是没有可回调的对象时,就会抛出一个StopIteration
异常。性能
In [22]: a Out[22]: [100, 200, 300] In [23]: b = iter(a) In [24]: print(type(b)) <class 'list_iterator'> In [25]: print(type(a)) <class 'list'> In [26]: print(next(b)) 100 In [27]: print(next(b)) 200 In [28]: print(next(b)) 300 In [29]: print(next(b)) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-29-0b064482c990> in <module>() ----> 1 print(next(b)) StopIteration:
能够经过isinstance(a,Iterator)来查看一个对象是不是迭代器。大数据
In [31]: from collections import Iterable,Iterator In [32]: a Out[32]: [100, 200, 300] In [33]: b Out[33]: <list_iterator at 0x7fc794482d30> In [34]: isinstance(a,Iterable) Out[34]: True In [35]: isinstance(a,Iterator) Out[35]: False In [36]: isinstance(b,Iterable) Out[36]: True In [37]: isinstance(b,Iterator) Out[37]: True In [38]: dir(b) Out[38]: ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
由此,能够总结出,迭代器必须含有__iter__
,__next__
方法。一个迭代器必定时一个可迭代对象,可是一个可迭代对象不必定是迭代器。spa
__next__
: 放回容器的下一个元素code
__iter__
: 返回迭代器自己orm
迭代器的优点:在构建迭代器是,不是将全部的元素一次性加载,而是等调用next
方法时返回元素,因此这占用内存不多。对象
自定义一个迭代器:
class CountDown: """建立一个迭代器""" def __init__(self, step): self.step = step def __next__(self): """返回容器下一个元素""" if self.step <= 0: raise StopIteration self.step -= 1 return self.step def __iter__(self): """返回迭代器自己""" return self for element in CountDown(5): print(element)
结果:
4 3 2 1 0
使用迭代器来迭代Fibonacci数:
# coding=utf-8 class FibIterator(object): def __init__(self,n): self.n = n self.current = 0 self.num1 = 0 self.num2 = 1 def __next__(self): if self.current < self.n: self.num1 , self.num2 = self.num2, self.num1 + self.num2 self.current += 1 return self.num1 else: raise StopIteration def __iter__(self): """返回迭代器自己""" return self if __name__ == "__main__": fib = FibIterator(10) for num in fib: print(num,end=" ")
结果:
1 1 2 3 5 8 13 21 34 55
利用迭代器,咱们能够在每次迭代获取数据(经过next()方法)时按照特定的规律进行生成。可是咱们在实现一个迭代器时,关于当前迭代到的状态须要咱们本身记录,进而才能根据当前状态生成下一个数据。为了达到记录当前状态,并配合next()函数进行迭代使用,所以能够采用一种更简便的语法,即生成器(generator)。
生成器是一种特殊的迭代器,可让编写返回元素序列的函数所须要的代码变得简单,高效,并非像建立迭代器代码同样冗长。
例子:Fibonacci数列使用生成器实现
def fib(all_num): a, b = 0, 1 current_num = 0 while current_num < all_num: a, b = b, a + b yield a current_num += 1 obj = fib(10) for num in obj: print(num,end=" ")
结果:
1 1 2 3 5 8 13 21 34 55 89
生成器函数和常规的函数都是使用def语句进行定义,可是器是基于yield
指令返回一个值。能够暂停一个函数并返回中间结果。当须要一个将返回一个序列或在循环中执行的函数时,就能够使用生成器,由于当这些元素被传递到另外一个函数中进行后续处理时,一次返回一个元素能够有效的提高总体性能。
总结:
使用了yield
关键字的函数就是生成器。
yield
的两个做用:1.保存当前的运行状态,而后暂停执行,即生成器(函数)挂起。2. 将yield
关键字后面表达式的值做为返回值返回,此时能够理解为return的做用。
能够使用next()函数让生成器从断点处继续执行,即唤醒生成器。
生成式表达式是一种实现生成器的便捷方式,将列表推导式的中括号替换为圆括号。
和列表推导式的区别:列表生成式能够直接建立一个表,可是生成器表达式是一种边循环边计算,使得列表的元素能够在循环过程当中一个个的推算出来,不须要建立完整的列表,从而节省了大量的空间。
In [43]: a = [ x*2 for x in range(5)] In [44]: a Out[44]: [0, 2, 4, 6, 8] In [45]: b = ( x*2 for x in range(5)) In [46]: b Out[46]: <generator object <genexpr> at 0x7fc7961cd5e8> In [47]: next(b) Out[47]: 0 In [48]: next(b) Out[48]: 2 In [49]: next(b) Out[49]: 4 In [50]: next(b) Out[50]: 6 In [51]: next(b) Out[51]: 8 In [52]: next(b) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-52-adb3e17b0219> in <module>() ----> 1 next(b) StopIteration: In [55]: b = ( x*2 for x in range(5)) In [56]: for i in b: ...: print(i) # 没有值,由于以前已经遍历完了。
总结:生成器是一种高级迭代器。生成器的优势是延迟计算,一次返回一个结果,这样很是适用于大数据量的计算。可是,使用生成器必需要注意的一点是:生成器只能遍历一次