手動訪問迭代器中的元素

迭代器是Python中最典型的特性之一,最基本的功能我們可以簡單的把迭代器看作是一種處理序列中的元素的方式,更多的,迭代器還可以進行自己創建,或者是在itertools模塊中選擇實用的迭代模式,構建生成器函數等等。

如何在不使用for循環的情況下處理某個可迭代對象中的元素

要手動訪問可迭代對象中的元素,可以使用next()函數,然後自己寫代碼來捕獲StopIteration異常,比如像這樣以手工的方式來讀取文本行:

def manual_iter():
with open(/etc/passwd) as f:
try:
while True:
line = next(f)
print(line, end=)
except StopIteration:
pass

一般情況下,StopIteration這玩意就是來通知我們迭代結束的,但是如果是手動使用next(),也可以命令它返回一個結束值:

def manual_iter2():
with open(/etc/passwd) as f:
while True:
line = next(f)
if line is None:
break
print(line, end=)
if __name__ == __main__:
manual_iter()

委託迭代

假設我們自己構建了一個自定義的容器對象,其內部持有一個可迭代對象,那麼如何才能讓這個容器完成迭代操作

一般來說,我們只需要定義一個_iter_()方法,然後把迭代請求委託到對象內部持有的容器上:

class Node:
def __init__(self, value):
self._value = value
self._children = []

def __repr__(self):
return Node({!r}).format(self._value)

def add_child(self, node):
self._children.append(node)

def __iter__(self):
return iter(self._children)

# Example
if __name__ == __main__:
root = Node(0)
child1 = Node(1)
child2 = Node(2)
root.add_child(child1)
root.add_child(child2)
# Outputs Node(1), Node(2)
for ch in root:
print(ch)

Python的迭代協議要求_iter_()返回一個特殊的迭代器對象,由該對象事項的_next_()方法來完成實際的迭代,當然,如果只是迭代另一個容器中的內容,就只需要轉發迭代請求就好

用生成器創建新的迭代模式

假設我們想實現一個自定義的迭代模式,讓它區別於常見的內建函數,我們就可以使用生成器來定義。比如這裡就有一個生成器可以產生某個範圍內的浮點數:

def frange(start, stop, increment):
x = start
while x < stop
yield x
x += increment

如果要使用這個函數,可以使用for循環來進行迭代:

>>> for n in frange(0, 4, 0.5)
... print(n)
...
0
0.5
1.0
1.5
2.0
2.5
3.0
3.5
>>>

在函數中只要出現了yield語句就會將其轉換成為一個生成器,但與普通函數不同,生成器只會響應迭代操作時才運行,比如這個:

def countdown(n):
print(Starting to count from, n)
while n > 0:
yield n
n -= 1
print(Done)

def gen_pattern():
for n in frange(0, 4, 0.5):
print(n)
print(list(frange(0, 1, 0.125)))

#生成器函數
# Create the generator, notice no output appears
c = countdown(3)
print(next(c))
print(next(c))
print(next(c))
print(next(c))

if __name__ == __main__:
gen_pattern()

這裡的核心特性就是生成器函數只會在迭代響應過程中的"next"操作時才會運行。一旦生成器函數返回,迭代就停止了。

參考書目

《Python CookBook》作者:【美】 David Beazley, Brian K. Jones

Github地址:

yidao620c/python3-cookbook?

github.com圖標
推薦閱讀:

相關文章