python中可迭代對象,迭代器,生成器

python中可迭代對象,迭代器,生成器

1. 可迭代對象:

在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__方法的對象都是可迭代對象。函數

2. 迭代器

迭代器是指能夠使用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

3. 生成器:

利用迭代器,咱們能夠在每次迭代獲取數據(經過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)
    # 沒有值,由於以前已經遍歷完了。

總結:生成器是一種高級迭代器。生成器的優勢是延遲計算,一次返回一個結果,這樣很是適用於大數據量的計算。可是,使用生成器必需要注意的一點是:生成器只能遍歷一次

相關文章
相關標籤/搜索