国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 在Python中使用itertools模塊中的組合函數(shù)的教程

在Python中使用itertools模塊中的組合函數(shù)的教程

2020-06-05 09:06Python教程網(wǎng) Python

這篇文章主要介紹了在Python中使用itertools模塊中的組合函數(shù)的教程,來自IBM官方技術(shù)文檔,需要的朋友可以參考下

理解新概念

Python V2.2 中引入了迭代器的思想。唔,這并不十分正確;這種思想的“苗頭”早已出現(xiàn)在較老的函數(shù) xrange() 以及文件方法 .xreadlines() 中了。通過引入 yield 關(guān)鍵字,Python 2.2 在內(nèi)部實(shí)現(xiàn)的許多方面推廣了這一概念,并使編程定制迭代器變得更為簡單( yield 的出現(xiàn)使函數(shù)轉(zhuǎn)換成生成器,而生成器反過來又返回迭代器)。

迭代器背后的動(dòng)機(jī)有兩方面。將數(shù)據(jù)作為序列處理通常是最簡單的方法,而以線性順序處理的序列通常并不需要都同時(shí)實(shí)際 存在。

x*() 前兆提供了這些原理的清晰示例。如果您想對某操作執(zhí)行成千上萬次,那么執(zhí)行您的程序可能要花些時(shí)間,但該程序一般不需要占用大量內(nèi)存。同樣,對于許多類型的文件,可以一行一行地處理,且不需要將整個(gè)文件存儲(chǔ)在內(nèi)存中。最好對其它所有種類的序列也進(jìn)行惰性處理;它們可能依賴于通過通道逐步到達(dá)的數(shù)據(jù),或者依賴于一步一步執(zhí)行的計(jì)算。

大多數(shù)時(shí)候,迭代器用在 for 循環(huán)內(nèi),就象真正的序列那樣。迭代器提供了 .next() 方法,它可以被顯式調(diào)用,但有百分之九十九的可能,您所看到的是以下行:

?
1
2
for x in iterator:
  do_something_with(x)

在對 iterator.next() 進(jìn)行幕后調(diào)用而產(chǎn)生 StopIteration 異常時(shí),該循環(huán)就被終止。順便說一下,通過調(diào)用 iter(seq) ,實(shí)際序列可以被轉(zhuǎn)換成迭代器 - 這不會(huì)節(jié)省任何內(nèi)存,但是在下面討論的函數(shù)中它會(huì)很有用。

Python 不斷發(fā)展的分裂性格

Python 對函數(shù)編程(FP)的觀點(diǎn)有點(diǎn)相互矛盾。一方面,許多 Python 開發(fā)人員輕視傳統(tǒng)的 FP 函數(shù) map() 、 filter() 和 reduce() ,常常建議使用“列表理解”來代替它們。但完整的 itertools 模塊恰恰是由與這些函數(shù)類型完全相同的函數(shù)組成的,只不過這些函數(shù)對“惰性序列”(迭代器)操作,而不是對完整的序列(列表,元組)操作。而且,Python 2.3 中沒有任何“迭代器理解”的語法,這似乎與列表理解擁有一樣的動(dòng)機(jī)。

我猜想 Python 最終會(huì)產(chǎn)生某種形式的迭代器理解,但這取決于找到合適于它們的自然語法。同時(shí),在 itertools 模塊中,我們擁有大量有用的組合函數(shù)。大致地,這些函數(shù)中的每一個(gè)都接受一些參數(shù)(通常包含一些基礎(chǔ)迭代器)并返回一個(gè)新迭代器。例如,函數(shù) ifilter() 、 imap() 和 izip() 都分別直接等同于缺少詞首 i 的內(nèi)置函數(shù)。

缺少的等價(jià)函數(shù)

itertools 中沒有 ireduce() ,盡管按道理很自然地應(yīng)該有這個(gè)函數(shù);可能的 Python 實(shí)現(xiàn)是:
清單 1. ireduce() 的樣本實(shí)現(xiàn)

?
1
2
3
4
5
6
7
8
9
def ireduce(func, iterable, init=None):
  if init is None:
    iterable = iter(iterable)
    curr = iterable.next()
  else:
    curr = init
  for x in iterable:
    curr = func(curr, x)
    yield curr

ireduce() 的用例類似于 reduce() 的用例。例如,假設(shè)您想要添加某個(gè)大型文件所包含的一列數(shù)字,但是當(dāng)滿足一個(gè)條件時(shí)就停止。您可以使用以下代碼來監(jiān)控正在計(jì)算的合計(jì)數(shù):
清單 2. 添加并合計(jì)一列數(shù)

?
1
2
3
4
5
from operator import add
from itertools import *
nums = open('numbers')
for tot in takewhile(condition, ireduce(add, imap(int, nums)):
  print "total =", tot

一個(gè)更實(shí)際的示例可能類似于將事件流應(yīng)用于有狀態(tài)對象上,例如應(yīng)用到 GUI 窗口小部件上。但是即使是上述簡單示例也顯示了迭代器組合器的 FP 風(fēng)格。

基本迭代器工廠

itertools 中的所有函數(shù)都可以用純 Python 輕松地實(shí)現(xiàn)為生成器。在 Python 2.3+ 中包含該模塊的要點(diǎn)是為一些有用的函數(shù)提供標(biāo)準(zhǔn)行為和名稱。盡管程序員可以編寫他們自己的版本,但是每個(gè)人實(shí)際創(chuàng)建的變體都會(huì)有點(diǎn)不兼容。但是,另一方面是要以高效率的 C 代碼實(shí)現(xiàn)迭代器組合器。使用 itertools 函數(shù)將比編寫您自己的組合器稍微快一些。標(biāo)準(zhǔn)文檔顯示了每個(gè) itertools 函數(shù)的等價(jià)純 Python 實(shí)現(xiàn),所以不需要在本文中重復(fù)這些內(nèi)容了。

itertools 中的函數(shù)再基本不過了 - 而且命名也完全不同 - 這樣從該模塊導(dǎo)入所有名稱可能就有意義了。例如,函數(shù) enumerate() 可能明顯地出現(xiàn)在 itertools 中,但是它在 Python 2.3+ 中卻是一個(gè)內(nèi)置函數(shù)。值得注意的是,您可以用 itertools 函數(shù)很方便地表達(dá) enumerate() :

?
1
2
from itertools import *
enumerate = lambda iterable: izip(count(), iterable)

讓我們首先看一下幾個(gè) itertools 函數(shù),它們 沒有將其它迭代器作為基礎(chǔ),而完全是“從頭”創(chuàng)建迭代器。 times() 返回一個(gè)多次產(chǎn)生同一對象的迭代器;在本質(zhì)上,這一能力比較有用,但它確實(shí)可以很好地替代使用過多的 xrange() 和索引變量,從而可以簡單地重復(fù)一個(gè)操作。即,不必使用:

?
1
2
for i in xrange(1000):
  do_something()

您現(xiàn)在就可以使用更中性的:

?
1
2
for _ in times(1000):
  do_something()

如果 times() 只有一個(gè)參數(shù),那么它只會(huì)重復(fù)產(chǎn)生 None 。函數(shù) repeat() 類似于 times() ,但它無界地返回同一對象。不管是在包含獨(dú)立 break 條件的循環(huán)中還是在象 izip() 和 imap() 這樣的組合器中,這個(gè)迭代器都很有用。

函數(shù) count() 有點(diǎn)類似于 repeat() 和 xrange() 的交叉。 count() 無界地返回連續(xù)整數(shù)(以可選的參數(shù)為開始)。但是,如果 count() 當(dāng)前不支持溢出到現(xiàn)在正確的 longs,那么您可能還是要使用 xrange(n,sys.maxint) ;它并不是完全無界的,但是對于大多數(shù)用途,它實(shí)際上是一回事。類似于 repeat() , count() 在其它迭代器組合器內(nèi)部特別有用。

組合函數(shù)

我們已經(jīng)順便提到了 itertools 中的幾個(gè)實(shí)際組合函數(shù)。 ifilter() 、 izip() 和 imap() 的作用就象您會(huì)期望從它們相應(yīng)的序列函數(shù)上獲得的作用。 ifilterfalse() 很方便,所以您不需要去掉 lambda 和 def 中的謂詞函數(shù)(而且這還節(jié)省了大量的函數(shù)調(diào)用開銷)。但是在功能上,您可以將 ifilterfalse() 定義為(大致的情況,忽略了 None 謂詞):

?
1
2
def ifilterfalse(predicate, iterable):
  return ifilter(lambda predicate: not predicate, iterable)

函數(shù) dropwhile() 和函數(shù) takewhile() 根據(jù)謂詞對迭代器進(jìn)行劃分。 dropwhile() 在直到滿足某個(gè)謂詞 之前忽略所產(chǎn)生的元素, takewhile() 在滿足某個(gè)謂詞 時(shí)就終止。 dropwhile() 跳過迭代器的不定數(shù)目的初始元素,所以它可能直到某個(gè)延遲后才開始迭代。 takewhile() 馬上開始迭代,但是如果被傳入的謂詞變?yōu)檎妫敲淳徒K止迭代器。

函數(shù) islice() 基本上就是列表分片的迭代器版本。您可以指定開始、停止和步長,就象使用常規(guī)的片。如果給定了開始,那么會(huì)刪除大量元素,直到被傳遞的迭代器到達(dá)滿足條件的元素為止。這是另一個(gè)我認(rèn)為可以對 Python 進(jìn)行改進(jìn)的情形 - 迭代器最好只識(shí)別片,就象列表所做的(作為 islice() 行為的同義詞)。

最后一個(gè)函數(shù) starmap() 在 imap() 基礎(chǔ)上略微有些變化。如果這個(gè)作為參數(shù)傳遞的函數(shù)獲取多個(gè)參數(shù),那么被傳遞的 iterable 會(huì)產(chǎn)生大小適合的元組。這基本上與包含多個(gè)被傳入 iterable 的 imap() 相同,只不過它包含先前與 izip() 結(jié)合在一起的 iterables 集合。

深入探討

itertools 中包含的函數(shù)是一個(gè)很好的開始。不使用其它函數(shù),只用這些函數(shù)就可以讓 Python 程序員更輕松地利用和組合迭代器。一般說來,迭代器的廣泛使用對 Python 的未來無疑是很重要的。但是除了過去所包含的內(nèi)容以外,我還要對該模塊的將來更新提幾點(diǎn)建議。您可以立即很方便地使用這些函數(shù) - 當(dāng)然,如果它們是后來被包含進(jìn)來的,那么名稱或接口細(xì)節(jié)會(huì)有所不同。

一種可能會(huì)很通用的類別是一些將多個(gè) iterable 作為參數(shù),隨后從每個(gè) iterable 產(chǎn)生單獨(dú)元素的函數(shù)。與此相對照的是, izip() 產(chǎn)生元素元組,而 imap() 產(chǎn)生從基本元素計(jì)算而來的值。我頭腦中很清晰的兩個(gè)安排是 chain() 和 weave() 。第一個(gè)在效果上類似于序列并置(但是有點(diǎn)惰性)。即,在您可能使用的純序列中,例如:

?
1
2
for x in ('a','b','c') + (1, 2, 3):
  do_something(x)

對于一般的 iterables,您可以使用:

?
1
2
for x in chain(iter1, iter2, iter3):
  do_something(x)

Python 實(shí)現(xiàn)是:
清單 3. chain() 的樣本實(shí)現(xiàn)

?
1
2
3
4
def chain(*iterables):
  for iterable in iterables:
    for item in iterable:
      yield item

使用 iterables,您還可以通過使它們分散排列來組合幾個(gè)序列。還沒有任何對序列執(zhí)行這樣相同操作的內(nèi)置語法,但是 weave() 本身也非常適用于完整的序列。下面是可能的實(shí)現(xiàn)(Magnus Lie Hetland 提出了 comp.lang.python 的類似函數(shù)):
清單 4. weave() 的樣本實(shí)現(xiàn)

?
1
2
3
4
5
6
7
8
9
def weave(*iterables):
  "Intersperse several iterables, until all are exhausted"
  iterables = map(iter, iterables)
  while iterables:
    for i, it in enumerate(iterables):
      try:
        yield it.next()
      except StopIteration:
        del iterables[i]

讓我來演示一下 weave() 的行為,因?yàn)閺膶?shí)現(xiàn)上看不是很明顯:

?
1
2
3
4
>>> for x in weave('abc', xrange(4), [10,11,12,13,14]):
...  print x,
...
a 0 10 b 1 11 c 2 12 13 3 14

即使一些迭代器到達(dá)終點(diǎn),但其余迭代器會(huì)繼續(xù)產(chǎn)生值,直到在某一時(shí)刻產(chǎn)生了所有可用的值為止。

我將另外只提出一個(gè)可行的 itertools 函數(shù)。提出這個(gè)函數(shù)主要是受到了構(gòu)思問題的函數(shù)編程方法的啟發(fā)。 icompose() 與上面提出的函數(shù) ireduce() 存在某種對稱。但是在 ireduce() 將值的(惰性)序列傳遞給某個(gè)函數(shù)并產(chǎn)生每個(gè)結(jié)果的地方, icompose() 將函數(shù)序列應(yīng)用于每個(gè)前趨函數(shù)的返回值。可以把 ireduce() 用于將事件序列傳遞給長期活動(dòng)的對象。而 icompose() 可能將對象重復(fù)地傳遞給返回新對象的賦值函數(shù)。第一種方法是相當(dāng)傳統(tǒng)的考慮事件的 OOP 方法,而第二種的思路更接近于 FP。

以下是可能的 icompose() 實(shí)現(xiàn):
清單 5. icompose() 的樣本實(shí)現(xiàn)

?
1
2
3
4
5
def icompose(functions, initval):
  currval = initval
  for f in functions:
    currval = f(currval)
    yield currval

結(jié)束語

迭代器 - 被認(rèn)為是惰性序列 - 是功能強(qiáng)大的概念,它開啟了 Python 編程的新樣式。但是在只把迭代器當(dāng)作數(shù)據(jù)源與把它作為一種序列來考慮之間存在著微妙的差別。這兩種想法本質(zhì)上哪一種都不見得比另一種更正確,但是后者開創(chuàng)了操作編程事件的一種組合性的簡略表達(dá)方法。 itertools 中的組合函數(shù)(尤其是它可能產(chǎn)生的一些類似于我建議的函數(shù))接近于編程的聲明樣式。對我而言,這些聲明樣式一般都更不易出錯(cuò)且更強(qiáng)大。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 在线免费av观看 | 天天久久| 求av网址| 自拍视频在线观看 | 日韩小视频在线观看 | 日韩精品一区二区在线观看 | 一级黄色大片 | 毛片免费在线 | 国产精品成人3p一区二区三区 | 国产1级片 | 欧美不卡视频 | 日韩中文字幕在线观看 | 另类国产ts人妖高潮系列视频 | 精品日韩一区二区 | 激情久久久 | 日本中文字幕一区 | 曰批免费视频播放免费 | 亚洲精品视频在线 | 久久香蕉综合 | 欧美日韩中文字幕在线 | 伊人久久婷婷色综合98网 | 欧美一二三 | 日韩精品 | 一区二区三区回区在观看免费视频 | 精品视频三区 | 国产亚洲一区二区三区 | 国产欧美日韩综合精品一区二区 | 亚洲国产精品视频一区 | 狠狠艹 | 亚洲天堂一区 | 欧产日产国产一区 | 美女扒开尿口来摸 | 亚洲一区二区久久 | 伦一区二区三区中文字幕v亚洲 | www.天天操| 亚洲久草视频 | 91视频免费观看 | 刺激网| 欧美日韩精品免费 | 亚洲精品乱码久久久久久蜜桃麻豆 | 国产视频中文字幕 |