1. 程式人生 > >Python:叠代器

Python:叠代器

ack trac 翻轉 解析式 file imp ret ever import

在使用Python的過程中,很容易混淆如下幾個關聯的概念:

  • 容器(container)
  • 可叠代對象(Iterable)
  • 叠代器(Iterator)
  • 生成器(generator)
  • 生成器表達式
  • {list, set, dict} 解析式

1.容器(container)

容器是用來儲存元素的一種數據結構,它支持隸屬測試,容器將所有數據保存在內存中,在Python中典型的容器有:

  • list, deque, ...
  • set,frozesets,...
  • dict, defaultdict, OrderedDict, Counter, ...
  • tuple, namedtuple, ...
  • str

通過判斷一個對象是否包含某個元素來確定它是否為一個容器

>>> assert 1 in [1,2,3]       # lists
>>> assert 4 not in [1,2,3]
>>> assert 1 in {1,2,3}       # sets
>>> assert 4 not in {1,2,3} 
>>> assert 1 in (12,3)        # tuples
>>> assert 4 not in (1,2,3)

字典容器通過檢查是否包含某個鍵來進行判斷

>>> d = {1:"foo", 2:"bar", 3:"qux"}
>>> assert 1 in d
>>> assert 4 in d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> assert "foo" in d
Traceback (most recent call last):
  File "<stdin>", line 1, in
<module> AssertionError

字符串通過檢查是否包含某個子 串來判斷

>>> s="foo"
>>> assert "f" in s
>>> assert "b" in s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

2.可叠代對象

如果給定一個list或tuple,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們稱為叠代(Iteration)。

很多容器都是可叠代對象,此外還有更多的對象同樣也是可叠代對象,比如處於打開狀態的files,sockets等等。但凡是可以返回一個 叠代器 的對象都可稱之為可叠代對象,聽起來可能有點困惑,沒關系,可叠代對象與叠代器有一個非常重要的區別。

>>> x=[1,2,3]
>>> y=iter(x)
>>> z=iter(x)
>>> next(y)
1
>>> next(y)
2
>>> next(z)
1
>>> type(x)
<class list>
>>> type(y)
<class list_iterator>

x 是一個可叠代對象,可叠代對象和容器一樣是一種通俗的叫法,並不是指某種具體的數據類型,list是可叠代對象,dict是可叠代對象,set也是可叠代對象。 y 和 z 是兩個獨立的叠代器,叠代器內部持有一個狀態,該狀態用於記錄當前叠代所在的位置,以方便下次叠代的時候獲取正確的元素。叠代器有一種具體的叠代器類型,比如 list_iterator , set_iterator 。可叠代對象實現了 __iter__ 和 __next__ 方法(python2中是 next 方法,python3是 __next__ 方法),這兩個方法對應內置函數 iter() 和 next() 。 __iter__ 方法返回可叠代對象本身,這使得他既是一個可叠代對象同時也是一個叠代器。

3.一些叠代工具

3.1並行叠代

>>> names=[greg,greg1,greg2]
>>> ages=[18,12,13]
>>> for i in range(len(names)):
    print(names[i]+ is +str(ages[i]))

    
greg2 is 13
greg2 is 13
greg2 is 13
>>> for n,a in zip(names,ages):
    print(names[i]+ is +str(ages[i]))

    
greg2 is 13
greg2 is 13
greg2 is 13

3.2 編號叠代

list1 = ["", "", "一個", "測試"]
for index, item in enumerate(list1):
    print(index, item)

0 這
12 一個
3 測試

3.2 翻轉和排序叠代

>>> sorted([2,6,3,1,5])
[1, 2, 3, 5, 6]
>>> sorted(Hello,world!)
[!, ,, H, d, e, l, l, l, o, o, r, w]
>>> list(reversed(Hello,world!))
[!, d, l, r, o, w, ,, o, l, l, e, H]
>>> ‘‘.join(reversed(Hello,world!))
!dlrow,olleH

4.叠代器(iterator)

它是一個帶狀態的對象,他能在你調用 next() 方法的時候返回容器中的下一個值,任何實現了 __next__() (python2中實現 next() )方法的對象都是叠代器,至於它是如何實現的這並不重要。

#叠代器,1,有iter方法。2,有next方法
# 可以使用isinstance()判斷一個對象是否是Iterable對象:
l=[1,2,3,4]
d=iter(l)
print(d) #<list_iterator object at 0x000002C34B71C160>
# list,tuple,dict,string:iterable
print(next(d))
print(next(d))
print(next(d))
print(next(d))

# for循環內部三件事:1,調用可叠代對象iter方法,返回叠代器對象
# 2,不斷調用叠代器對象的next方法
# 3,處理StopIteration,遇到退出
# for i in [1,2,3,4]:
#     iter([1,2,3,4])

from collections import Iterator,Iterable
print(isinstance(2,list))#False
l=[1,2,3,4]
d=iter(l)
print(d)
print(isinstance(l,list))
print(isinstance(l,Iterable))
print(isinstance({}, Iterable))
print(isinstance(abc, Iterable))
print(isinstance((x for x in range(10)), Iterable))
print(isinstance(100, Iterable))#False

# 小結
# 凡是可作用於for循環的對象都是Iterable類型;
# 凡是可作用於next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;
# 集合數據類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。
# Python的for循環本質上就是通過不斷調用next()函數實現的,例如:


# 首先獲得Iterator對象:
it = iter([1, 2, 3, 4, 5])
while True:# 循環:
    try:# 獲得下一個值:
        x = next(it)
    except StopIteration:# 遇到StopIteration就退出循環
        break

可以使用叠代器來解決復用可占空間的問題

class Fab(object):
    def __init__(self, max):
        self.max = max
        self.n, self.a, self.b = 0, 0, 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.n < self.max:
            r = self.b
            self.a, self.b = self.b, self.a + self.b
            self.n = self.n + 1
            return r
        raise StopIteration()

for key in Fab(5):
    print(key)
    
# 1
# 1
# 2
# 3
# 5

Fab既是一個可叠代對象(因為它實現了 __iter__ 方法),又是一個叠代器(因為實現了 __next__ 方法)。實例變量 self .a 和 self.b 用戶維護叠代器內部的狀態。每次調用 next() 方法的時候做兩件事:

  1. 為下一次調用 next() 方法修改狀態
  2. 為當前這次調用生成返回結果

叠代器就像一個懶加載的工廠,等到有人需要的時候才給它生成值返回,沒調用的時候就處於休眠狀態等待下一次調用。

5.從叠代器得到序列

list構造方法顯式將叠代器轉化為列表

class TestIterator:
    value=0
    def __next__(self):
        self.value +=1
        if self.value>10:
            raise StopIteration
        return self.value
    def __iter__(self):
        return self

ti=TestIterator()
print(list(ti))
#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Python:叠代器