程序设计 - 关于 Python 列表推导的疑惑
伊谢尔伦
伊谢尔伦 2017-04-17 13:44:40
0
3
332

关于

Python list comprehension 其实就是 generator.

该怎么理解?

另外 map filter、generator 也让人挺不解的,求python 大牛都给解释下。这么设计的缘由是什么?

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

全部回覆(3)
伊谢尔伦

首先關於問題裡面引用的那句話:不要這樣理解,會把自己繞進去,而且也不準確。

這個問題要往簡單來看。對於一個簡單的 list comprehension [x**2 for x in range(10)],它等價於:

l = []

for x in range(10):
    l.append(x**2)

所以,list comprehension 只是一個語法糖,能讓容器的初始化變得更加簡潔,但它本質上還是在往容器裡不斷塞東西。 (當然,由於這個語法存在,python 也可以針對性的最佳化效能,效能會比自己 append 好一些)

List comprehensions provide a concise way to create lists.
List comprehensions 提供了一種簡潔明了的方式來創建 list
來自 python 官方文件

它跟 generator 概念不一樣,如果要說的話,迭代器(iterator)可能才是描述 x**2 for x in range(10) 這種語法的正確方法,雖然它的名字確實叫做 generator expression。

其次,什麼是 generator。

這個概念本身是很晦澀,如果初學不要強行理解。

簡單說它就是一個資料產生器,或精確點說,它是個呼叫者可控制的迭代器(iterator),僅此而已。

Generator 函數就像一個扭蛋機,使用者每次投入一枚硬幣它就吐出一顆扭蛋。

  • 扭蛋機不知道也不關心使用者是誰
  • 使用者不知道也不關心下次吐出的扭蛋是什麼
  • 使用想要扭蛋的時候就投幣,立即就會出一個扭蛋,或者告訴他已經沒有庫存了
  • 當使用者不需要扭蛋的時候,他就可以一直無視這個扭蛋機

這樣設計的好處是,耦合低可控

至於 generator 的高階用法,例如模擬 coroutine 什麼的,可以暫時無視。

最後,關於 mapfilter 等函數的設計思路。

從 generator 的特性可以看出,它所能表達的只能是一種順序輸出的情況,無法後悔,除非從頭開始。

這就像一條工廠的流水線,只能向前不能後退。

如果我們有這樣一條流水線,我們能做什麼呢?

  • 管線的入口接著一個 generator,源源不絕的從 generator 輸出到管線
  • 我們可以對流水線上的東西進行加工,一塊鋼板在上面銼一下變成某米的後蓋,這就是 map
  • 我們可以把管線上的殘次品丟掉,這就是 filter

管線生產是工業時代智慧體現,能夠將執行效率做到最高,且管線上各個環節都沒有耦合性,它的合理性相當明顯。

PHPzhong

這樣處理主要是 Lazy 求值的做法

設想一些應用場景,你需要對1000萬個斐波那切數相加求和。

  • 一個方法是先用一個列表,寫一個函數,直接產生1000萬個個斐波那切數,然後再把1000萬個存儲,然後迭代這個list的每一個數進行疊加求和。 (先生成,再處理)
  • 另外一種方式就是,寫一個能依照要求,每次產生一個斐波那切數函數,求和的過程為每調用函數,產生一個斐波那切數,然後進行求和一次。 (一邊生成一遍處理)

第二種方法,就是一種 lazy 的方式,也就是 python 慣用的 generator

Peter_Zhu

不知道題主這句話是從何得來的,我測試的Python2.7就是轉化成for函數而已如下.

不知道Py3.*中是否也是如此(可能變了吧)

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!