Python中的“迭代”詳解

迭代器模式:一種惰性獲取數(shù)據(jù)項(xiàng)的方式,即按需一次獲取一個(gè)數(shù)據(jù)項(xiàng)嚷硫。

關(guān)于迭代器和生成器的區(qū)別:

在Python社區(qū)中检访,大多數(shù)時(shí)候把迭代器和生成器視為同一概念。

如果需要細(xì)分的話仔掸,那么迭代器用于從集合中取出數(shù)據(jù)烛谊,而生成器用于憑空生成元素。

一嘉汰、序列

所有序列都是可以迭代的丹禀。我們接下來要實(shí)現(xiàn)一個(gè) Sentence(句子)類,我們向這個(gè)類的構(gòu)造方法傳入包含一些文本的字符串鞋怀,然后可以逐個(gè)單詞迭代双泪。

sentence.py

import re
import reprlib

RE_WORD = re.compile('\w+')


class Sentence:
    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)  # re.findall 函數(shù)返回一個(gè)字符串列表

    def __getitem__(self, index):
        return self.words[index]

    def __len__(self):
        return len(self.words)

    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)  # reprlib.repr 函數(shù)用于生成大型數(shù)據(jù)結(jié)構(gòu)的簡略字符串表示形式

接下來測試 Sentence 實(shí)例能否迭代

In [11]: s = sentence.Sentence("'winter is coming!', he said.")

In [12]: s
Out[12]: Sentence("'winter is c...g!', he said.")

In [13]: for word in s:
    ...:     print(word)
    ...:     
winter
is
coming
he
said

In [14]: list(s)
Out[14]: ['winter', 'is', 'coming', 'he', 'said']

序列可以迭代的原因:

iter()

解釋器需要迭代對象 x 時(shí),會自動調(diào)用iter(x)密似。

內(nèi)置的 iter 函數(shù)有以下作用:

  1. 檢查對象是否實(shí)現(xiàn)了__iter__方法焙矛,如果實(shí)現(xiàn)了就調(diào)用他,獲取一個(gè)迭代器残腌。
  2. 如果沒有實(shí)現(xiàn)__iter__方法村斟,但是實(shí)現(xiàn)了__getitem__方法贫导,Python會創(chuàng)建一個(gè)迭代器,嘗試按順序(從索引 0 開始)獲取元素蟆盹。
  3. 如果嘗試失敗孩灯,Python 拋出 TypeError 異常,通常會提示"XXX object is not iterable"逾滥,其中 XXX 是目標(biāo)對象所屬的類峰档。

由于序列都實(shí)現(xiàn)了__getitem__方法,所以都可以迭代寨昙。

從 Python3.4 開始讥巡,檢查對象 x 能否迭代,最準(zhǔn)確的方式是調(diào)用 iter(x)舔哪,如果不可迭代欢顷,再處理 TypeError 異常,這比使用 isistance(x, abc.Iterable)更準(zhǔn)確捉蚤,因?yàn)閕ter(x)函數(shù)會考慮__getitem__方法抬驴。

二、可迭代對象與迭代器的對比

可迭代對象:使用內(nèi)置函數(shù) iter() 可以獲取迭代器的對象外里。

與迭代器的關(guān)系:Python 從可迭代對象中獲取迭代器怎爵。

下面用for循環(huán)迭代一個(gè)字符串,這里字符串 'abc' 是可迭代的對象盅蝗,用 for 循環(huán)迭代時(shí)是有生成器鳖链,只是 Python 隱藏了。

In [19]: s = 'abc'

In [20]: for char in s:
    ...:     print(char)
    ...:     
    ...:     
a
b
c

如果沒有 for 語句墩莫,使用 while 循環(huán)模擬芙委,要寫成下面這樣:

In [21]: s = 'abc'

In [22]: it = iter(s)  # 使用可迭代對象構(gòu)建迭代器

In [23]: while True:
    ...:     try:
    ...:         print(next(it)) # 在迭代器上不斷調(diào)用 next() 獲取下一個(gè)字符
    ...:     except StopIteration: # 如果沒有字符了,迭代器會拋出 StopIteration 異常
    ...:         del it # 釋放對 it 的引用狂秦,即廢棄迭代器對象
    ...:         break
    ...:     
a
b
c

Python 內(nèi)部會處理 for 循環(huán)和其他迭代上下文(如列表推導(dǎo)灌侣,元組拆包等等)中的 StopIteration 異常。

標(biāo)準(zhǔn)的迭代器接口有兩個(gè)方法:

__next__:返回下一個(gè)可用的元素裂问,如果沒有元素了侧啼,拋出 StopIteration 異常。

__iter__:返回 self堪簿,以便在需要使用可迭代對象的地方使用迭代器痊乾,如 for 循環(huán)中。

迭代器:實(shí)現(xiàn)了無參數(shù)的__next__方法椭更,返回序列中的下一個(gè)元素哪审;如果沒有元素了,那么拋出 StopIteration 異常虑瀑。Python 中的迭代器還實(shí)現(xiàn)了__iter__方法湿滓,因此迭代器也可以迭代滴须。

接下來使用迭代器模式實(shí)現(xiàn) Sentence 類:

sentence_iter.py

import re
import reprlib

RE_WORD = re.compile('\w+')



# 可迭代對象類
class Sentence:
    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)

    def __iter__(self):
        # 實(shí)例化一個(gè)新的迭代器
        return SentenceIterator(self.words)

   
# 迭代器類
class SentenceIterator:
    def __init__(self, words):
        self.words = words
        self.index = 0

    # 實(shí)現(xiàn) __next__ 返回單個(gè)元素
    def __next__(self):
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return word
    
    # 實(shí)現(xiàn) __iter__ 返回自身
    def __iter__(self):
        return self

注意,不要在 Sentence 類中實(shí)現(xiàn) __next__ 方法叽奥,讓 Sentence 實(shí)例既是可迭代對象扔水,也是自身的迭代器。

迭代器模式可用來:

  • 訪問一個(gè)聚合對象的內(nèi)容而無需暴露它的內(nèi)部表示
  • 支持對聚合對象的多種遍歷
  • 為遍歷不同的聚合結(jié)構(gòu)提供一個(gè)統(tǒng)一的接口(即支持多臺迭代)

為了“支持多種遍歷”而线,必須能從同一個(gè)可迭代的實(shí)例中獲取多個(gè)獨(dú)立的迭代器铭污,而且各個(gè)迭代器要能維護(hù)自身的內(nèi)部狀態(tài)恋日,因此這一模式正確的實(shí)現(xiàn)方式是膀篮,每次調(diào)用 iter(my_iterable) 都新建一個(gè)獨(dú)立的迭代器。

所以總結(jié)下來就是:

  • 可迭代對象一定不能是自身的迭代器岂膳,也就是說誓竿,可迭代對象必須實(shí)現(xiàn) __iter__方法,但是不能實(shí)現(xiàn)__next__方法
  • 迭代器應(yīng)該一直可以迭代谈截,而且他的__iter__方法應(yīng)該返回自身筷屡。

三、生成器

實(shí)現(xiàn)相同功能簸喂,但卻符合 Python 習(xí)慣的方式是毙死,用生成器函數(shù)代替 SentenceIteror 類。

sentence_gen.py

import re
import reprlib

RE_WORD = re.compile('\w+')


class Sentence:
    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)
    
    # 是一個(gè)生成器函數(shù)喻鳄,調(diào)用時(shí)會構(gòu)建一個(gè)實(shí)現(xiàn)了迭代器接口的生成器對象扼倘,因此不用再定義 SentenceIterator類了。
    def __iter__(self):
        for word in self.words:
            yield word

只要 Python 函數(shù)的定義體中有 yield 關(guān)鍵字除呵,該函數(shù)就是生成器函數(shù)再菊。調(diào)用生成器函數(shù),就會返回一個(gè)生成器對象颜曾。

生成器函數(shù)會創(chuàng)建一個(gè)生成器對象纠拔,包裝生成器函數(shù)的定義體,把生成器傳給 next(...) 函數(shù)時(shí)泛豪,生成器函數(shù)會向前稠诲,執(zhí)行函數(shù)定義體中的下一個(gè) yield 語句,返回產(chǎn)出的值诡曙,并在函數(shù)定義體的當(dāng)前位置暫停臀叙,。最終岗仑,函數(shù)的定義體返回時(shí)匹耕,外層的生成器對象會拋出 StopIteration 異常,這一點(diǎn)與迭代器協(xié)議一致荠雕。

注意稳其,我說的是產(chǎn)出或生成值驶赏。調(diào)用生成器函數(shù)返回生成器,生成器產(chǎn)出或生成值既鞠。生成器不會以常規(guī)的方式“返回”值煤傍,生成器函數(shù)定義體中的 return 語句會觸發(fā)生成器對象拋出 StopIteration 異常。(Python3.3 之前有 return 語句會報(bào)錯(cuò))

關(guān)于 for 循環(huán):

for 循環(huán)會隱式的調(diào)用 next()嘱蛋,而且在使用 for 循環(huán)到生成器函數(shù)定義體的末尾時(shí)蚯姆,for 循環(huán)會捕獲異常,因此循環(huán)終止時(shí)沒有報(bào)錯(cuò)洒敏。

如今這一版 Sentence 類相較之前簡短多了龄恋,但是還不夠慵懶。惰性凶伙,是如今人們認(rèn)為最好的特質(zhì)郭毕。惰性實(shí)現(xiàn)是指盡可能延后生成值,這樣做能節(jié)省內(nèi)存函荣,或許還能避免做無用的處理显押。

四、惰性實(shí)現(xiàn)

目前實(shí)現(xiàn)的幾版 Sentence 類都不具有惰性傻挂,因?yàn)?__init__方法急迫的構(gòu)建好了文本中的單詞列表乘碑,然后將其綁定到 self.words 屬性上。這樣就得處理整個(gè)文本金拒,列表使用的內(nèi)存量可能與文本本身一樣多(或許更多兽肤,取決于文本中有多少非單詞字符)。

re.finditer 函數(shù)是 re.findall函數(shù)的惰性版本殖蚕,返回的是一個(gè)生成器轿衔,按需生成 re.MatchObject 實(shí)例。我們可以使用這個(gè)函數(shù)來讓 Sentence 類變得懶惰睦疫,即只在需要時(shí)才生成下一個(gè)單詞害驹。

sentence_gen2.py


import re
import reprlib

RE_WORD = re.compile('\w+')


class Sentence:
    def __init__(self, text):
        self.text = text

    def __repr__(self):
        return "Sentence(%s)" % reprlib.repr(self.text)

    def __iter__(self):
        for match in RE_WORD.finditer(self.text):
            yield match.group() # match.group()方法從 MatchObject 實(shí)例中提取匹配正則表達(dá)式的具體文本。

五蛤育、標(biāo)準(zhǔn)庫中的生成器函數(shù)

標(biāo)準(zhǔn)庫提供了很多生成器函數(shù)宛官,有用于逐行迭代純文本文件的對象,還有出色的 os.walk 函數(shù)等等瓦糕。本節(jié)專注于通用的函數(shù):參數(shù)為任意的可迭代對象底洗,返回值是生成器,用于生成選中的咕娄、計(jì)算出的和重新排列的元素亥揖。

第一組是用于過濾的生成器函數(shù):從輸入的可迭代對象中產(chǎn)出元素的子集,而且不修改元素本身。這種函數(shù)大多數(shù)都接受一個(gè)斷言參數(shù)(predicate)费变,這個(gè)參數(shù)是個(gè)布爾函數(shù)摧扇,有一個(gè)參數(shù),會應(yīng)用到輸入中的每個(gè)元素上挚歧,用于判斷元素是否包含在輸出中扛稽。

模塊 函數(shù) 說明
itertools compress(it, selector_it) 并行處理兩個(gè)可迭代的對象,如果 selector_it 中的元素是真值(非0滑负,非空)在张,產(chǎn)出 it 中對應(yīng)的元素
itertools dropwhile(predicate, it) 處理 it,跳過 predicate 的計(jì)算結(jié)果為真值的元素矮慕,然后產(chǎn)出剩下的各個(gè)元素(不再進(jìn)一步檢查)
內(nèi)置 filter(predicate, it) 把 it 中的各個(gè)元素傳給 predicate帮匾,如果 predicate(item) 返回真值,那么產(chǎn)出對應(yīng)的元素凡傅,如果 predicate 是None辟狈,那么只產(chǎn)出真值元素影涉。
itertools filterfalse(predicate, it) 與 filter 函數(shù)類似撕攒,不過 predicate 的邏輯是相反的蓉冈,prediacate 返回假值時(shí)產(chǎn)出對應(yīng)的元素
itertools islice(it, stop) 或 islice(it, start, stop, step=1) 產(chǎn)出 it 的切片,作用類似于 s[:stop] 或 s[start:stop:step]槽华,不過 it 可以是任何可迭代對象,而且這個(gè)函數(shù)實(shí)現(xiàn)的是惰性操作
itertools takewhile(predicate, it) predicate 返回真值時(shí)產(chǎn)出對應(yīng)的元素趟妥,然后立即停止猫态,不再繼續(xù)檢查,返回假值立即停止披摄。

以下為這些函數(shù)的演示:

>>> def vowel(c):
...     return c.lower() in 'aeiou'
... 
>>> list(filter(vowel, 'Aardvark'))
['A', 'a', 'a']
>>> import itertools
>>> list(itertools.filterfalse(vowel, 'Aardvark'))
['r', 'd', 'v', 'r', 'k']
>>> list(itertools.dropwhile(vowel, 'Aardvark'))
['r', 'd', 'v', 'a', 'r', 'k'] # 不再進(jìn)一步檢查亲雪,即相同真值只跳過一次
>>> list(itertools.takewhile(vowel, 'Aardvark'))
['A', 'a'] # 同上,不再進(jìn)一步檢查
>>> list(itertools.compress('Aardvark', (1, 0, 1, 1, 0, 1)))
['A', 'r', 'd', 'a'] # selector_it 是(1, 0, 1, 1, 0, 1)疚膊,所以'Aardvark'中位置對應(yīng)1的生成出來了义辕。
>>> list(itertools.islice('Aardvark', 4))
['A', 'a', 'r', 'd']
>>> list(itertools.islice('Aardvark', 4, 7))
['v', 'a', 'r']
>>> list(itertools.islice('Aardvark', 1, 7, 2))
['a', 'd', 'a']

第二組是用于映射的生成器函數(shù):在輸入的單個(gè)/多個(gè)可迭代對象中的各個(gè)元素上做計(jì)算,然后返回結(jié)果寓盗。

模塊 函數(shù) 說明
itertools accumulate(it, [func]) 產(chǎn)出累積的總和灌砖,如果提供了 func,那么把前兩個(gè)元素傳給它傀蚌,然后把計(jì)算結(jié)果和下一個(gè)元素傳給它基显,以此類推,最后產(chǎn)出結(jié)果
內(nèi)置 enumerate(iterable, start=0) 產(chǎn)出由兩個(gè)元素組成的元組善炫,結(jié)構(gòu)是(index, item)撩幽,其中 index 從 start 開始計(jì)數(shù),item 則從 iterable 中獲取
內(nèi)置 map(func, it1, [it2, ..., itN]) 把 it 中的各個(gè)元素傳給 func箩艺,產(chǎn)出結(jié)果窜醉,如果傳入 N 個(gè)可迭代的對象制跟,那么 func 必須能接受 N 個(gè)參數(shù),而且要并行處理各個(gè)可迭代的對象
itertools starmap(func, it) 把 it 中的各個(gè)元素傳給 func酱虎,產(chǎn)出結(jié)果雨膨,輸入的可迭代對象應(yīng)該產(chǎn)出可迭代的元素 iit,然后以 func(*iit) 這種形式調(diào)用 func

以下為這些函數(shù)的用法:

>>> sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
>>> import itertools
>>> list(itertools.accumulate(sample))
[5, 9, 11, 19, 26, 32, 35, 35, 44, 45]
>>> import operator
>>> list(itertools.accumulate(range(1, 11), operator.mul)) # 1! 到 10!的階乘
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] 
>>> list(map(operator.mul, range(11), range(11)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> list(map(operator.mul, range(11), [2, 4, 8]))
[0, 4, 16]
>>> list(itertools.starmap(operator.mul, enumerate('albatroz', 1))) # 從 1 開始读串,根據(jù)字母所在位置聊记,把字母重復(fù)相應(yīng)的次數(shù)
['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz']

第三組是用于合并的生成器函數(shù),這些函數(shù)都可以從輸入的多個(gè)可迭代對象中產(chǎn)出元素恢暖。

模塊 函數(shù) 說明
itertools chain(it1, ..., itN) 先產(chǎn)出 it1 中的所有元素排监,然后產(chǎn)出 it2 中的所有元素,以此類推杰捂,無縫連接在一起舆床。
itertools chain.from_iterable(it) 產(chǎn)出 it 生成的各個(gè)可迭代對象中的元素,無縫連接在一起嫁佳。it 應(yīng)該可以產(chǎn)出可迭代元素挨队,例如可迭代的對象的列表
itertools product(it1, ..., itN, repeat=1) 計(jì)算笛卡爾積:從輸入的各個(gè)可迭代對象中獲取元素,合并成由 N 個(gè)元素組成的元組蒿往,與嵌套的 for 循環(huán)效果一樣盛垦;repeat 指明重復(fù)處理多少次輸入的可迭代對象
內(nèi)置 zip(it1, ..., itN) 并行從輸入的各個(gè)可迭代對象中獲取元素,產(chǎn)出由 N 個(gè)元素組成的元組瓤漏,只要有一個(gè)可迭代對象到頭了腾夯,就默默的停止
itertools zip_longest(it1, ..., itN, fillvalue=None) 并行從輸入的各個(gè)可迭代對象中獲取元素,產(chǎn)出由 N 個(gè)元素組成的元組蔬充,等到最長的可迭代對象到頭后才停止蝶俱,空缺的值使用 fillvalue 填充。

以下為演示:

>>> list(itertools.chain('ABC', range(2)))
['A', 'B', 'C', 0, 1]
>>> list(itertools.chain.from_iterable(enumerate('ABC')))
[0, 'A', 1, 'B', 2, 'C']
>>> list(zip('ABC', range(5)))
[('A', 0), ('B', 1), ('C', 2)]
>>> list(itertools.zip_longest('ABC', range(5), fillvalue='?'))
[('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)]
>>> list(itertools.product('ABC', range(2)))
[('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]

第四組是從一個(gè)元素中產(chǎn)出多個(gè)值饥漫,擴(kuò)展輸入的可迭代對象榨呆。

模塊 函數(shù) 說明
itertools combinations(it, out_len) 把 it 產(chǎn)出的 out_len 個(gè)元素組合在一起,然后產(chǎn)出
itertools combinations_with_replacement(it, out_len) 把 it 產(chǎn)出的 out_len 個(gè)元素組合在一起趾浅,然后產(chǎn)出愕提,包含相同元素的組合
itertools count(start=0, step=1) 從 start 開始不斷產(chǎn)出數(shù)字,按 step 指定的步幅增加
itertools cycle(it) 從 it 中產(chǎn)出各個(gè)元素皿哨,存儲各個(gè)元素的副本浅侨,然后按順序重復(fù)不斷的產(chǎn)出各個(gè)元素
itertools permutations(it, out_len=None) 把 out_len 個(gè) it 產(chǎn)出的元素排列在一起,然后產(chǎn)出這些排列证膨,out_len 的默認(rèn)值等于 len(list(it))
itertools repeat(item, [times]) 重復(fù)不斷的產(chǎn)出指定的元素如输,除非提供 times,指定次數(shù)

以下為演示:

>>> ct = itertools.count()
>>> next(ct), next(ct), next(ct)
(0, 1, 2)
>>> list(itertools.islice(cy, 7))
['A', 'B', 'C', 'A', 'B', 'C', 'A']
>>> list(itertools.repeat(7, 4))
[7, 7, 7, 7]
>>> list(map(operator.mul, range(11), itertools.repeat(5))) # repeat 常見用途:為 map 函數(shù)提供固定參數(shù)
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
>>> list(itertools.combinations('ABC', 2)) # 'ABC'中每兩個(gè)元素的各種組合,元素順序無意義不见,不含相同元素的組合
[('A', 'B'), ('A', 'C'), ('B', 'C')]
>>> list(itertools.combinations_with_replacement('ABC', 2)) # 'ABC'中每兩個(gè)元素的各種組合澳化,元素順序無意義,含相同元素的組合
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
>>> list(itertools.permutations('ABC',2)) # 'ABC'中每兩個(gè)元素的各種排列稳吮,元素的順序有意義
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]

第五組生成器函數(shù)用于產(chǎn)出輸入的可迭代對象中的全部元素缎谷,不過會以某種方式重新排列。

模塊 函數(shù) 說明
itertools groupby(it, key=None) 產(chǎn)出由兩個(gè)元素組成的元素灶似,形式為(key, group)列林,其中 key 是分組標(biāo)準(zhǔn),group 是生成器酪惭,用于產(chǎn)出分組里的元素
內(nèi)置 reversed(seq) 從后向前希痴,倒序產(chǎn)出seq中的元素,seq必須是序列春感,或者是實(shí)現(xiàn)了 __reversed__特殊方法的對象
itertools tee(it, n=2) 產(chǎn)出一個(gè)由 n 個(gè)生成器組成的元組砌创,每個(gè)生成器用于單獨(dú)產(chǎn)出輸入的可迭代對象中的元素
>>> import itertools
>>> list(itertools.groupby('LLLAAAXXXX'))
[('L', <itertools._grouper object at 0x7f467ea946a0>), ('A', <itertools._grouper object at 0x7f467ea946d8>), ('X', <itertools._grouper object at 0x7f467ea94710>)]
>>> for char, group in itertools.groupby('LLLAAAXXXX'):
...     print(char, '->', list(group))
... 
L -> ['L', 'L', 'L']
A -> ['A', 'A', 'A']
X -> ['X', 'X', 'X', 'X']
>>> words = ['x','ss','zzz','dsas','xs']
>>> words.sort(key=len) # 使用 groupby 時(shí)需要先進(jìn)行排序或進(jìn)行分組
>>> words
['x', 'ss', 'xs', 'zzz', 'dsas']
>>> for length, group in itertools.groupby(words, len):
...     print(length, '->', list(group))
... 
1 -> ['x']
2 -> ['ss', 'xs']
3 -> ['zzz']
4 -> ['dsas']

>>> g1, g2 = itertools.tee('ABC')
>>> next(g1)
'A'
>>> next(g1)
'B'
>>> next(g2)
'A'
>>> list(g2)
['B', 'C']

六、可迭代的歸約函數(shù)

下面的函數(shù)都接受一個(gè)可迭代的對象鲫懒,然后返回單個(gè)結(jié)果嫩实,這種函數(shù)叫“歸約函數(shù)”,“合攏函數(shù)”或“累加函數(shù)”刀疙,其實(shí)舶赔,這些內(nèi)置函數(shù)都可以用 functools.reduce 函數(shù)實(shí)現(xiàn),但內(nèi)置更加方便谦秧,而且還有一些優(yōu)點(diǎn)。

模塊 函數(shù) 說明
內(nèi)置 all(it) it 中的所有元素都為真值時(shí)返回 True撵溃,否則返回 False疚鲤;all([]) 返回 True
內(nèi)置 any(it) 只要 it 中有元素為真值就返回 True,否則返回 False缘挑;any([]) 返回 False
內(nèi)置 max(it, [key=], [default=]) 返回 it 中值最大的元素集歇,key 是排序函數(shù),與 sorted 函數(shù)中一樣语淘;如果可迭代的對象為空诲宇,返回 default
內(nèi)置 min(it, [key=], [default=]) 返回 it 中值最小的元素,key 是排序函數(shù)惶翻,與 sorted 函數(shù)中一樣姑蓝;如果可迭代的對象為空,返回 default
functools reduce(func, it, [initial]) 把前兩個(gè)元素傳給 func吕粗,然后把計(jì)算結(jié)果和第三個(gè)元素傳給 func纺荧,以此類推,返回最后的結(jié)果,如果提供了 initial 宙暇,把它當(dāng)做第一個(gè)元素傳入输枯。
內(nèi)置 sum(it, start=0) it 中所有元素的總和,如果提供可選的 start占贫,會把它加上(計(jì)算浮點(diǎn)數(shù)的加法時(shí)桃熄,可以使用 math.fsum 函數(shù)提高精度

參考教程:
《流暢的python》 P330 - 363

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市型奥,隨后出現(xiàn)的幾起案子蜻拨,更是在濱河造成了極大的恐慌,老刑警劉巖桩引,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缎讼,死亡現(xiàn)場離奇詭異,居然都是意外死亡坑匠,警方通過查閱死者的電腦和手機(jī)血崭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厘灼,“玉大人夹纫,你說我怎么就攤上這事∩璋迹” “怎么了舰讹?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闪朱。 經(jīng)常有香客問我月匣,道長,這世上最難降的妖魔是什么奋姿? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任锄开,我火速辦了婚禮,結(jié)果婚禮上称诗,老公的妹妹穿的比我還像新娘萍悴。我一直安慰自己,他們只是感情好寓免,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布癣诱。 她就那樣靜靜地躺著,像睡著了一般袜香。 火紅的嫁衣襯著肌膚如雪撕予。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天困鸥,我揣著相機(jī)與錄音嗅蔬,去河邊找鬼剑按。 笑死,一個(gè)胖子當(dāng)著我的面吹牛澜术,可吹牛的內(nèi)容都是我干的艺蝴。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼鸟废,長吁一口氣:“原來是場噩夢啊……” “哼猜敢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盒延,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤缩擂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后添寺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胯盯,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年计露,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了博脑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡票罐,死狀恐怖叉趣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情该押,我是刑警寧澤疗杉,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站蚕礼,受9級特大地震影響烟具,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜闻牡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一净赴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧罩润,春花似錦、人聲如沸翼馆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽应媚。三九已至严沥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間中姜,已是汗流浹背消玄。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工跟伏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翩瓜。 一個(gè)月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓受扳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親兔跌。 傳聞我的和親對象是個(gè)殘疾皇子勘高,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348