成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Python語(yǔ)言中計(jì)數(shù)方法的演變

sunsmell / 1976人閱讀

摘要:譯文鏈接編程派有時(shí)候,利用語(yǔ)言簡(jiǎn)潔優(yōu)雅地解決問(wèn)題的方法,會(huì)隨著時(shí)間變化。隨著不斷進(jìn)化,統(tǒng)計(jì)列表元素?cái)?shù)量的方法也在改變。最后將字典中相應(yīng)鍵的值設(shè)置為新的計(jì)數(shù)。我們發(fā)現(xiàn)這種方法比之前的代碼更加簡(jiǎn)潔優(yōu)雅,所以提交了此次修改。

文中如對(duì)專(zhuān)業(yè)術(shù)語(yǔ)的翻譯有誤,請(qǐng)Python高手指正(Pythonistas),謝謝!另外,原文中的Pythonic一詞,大意指符合Python語(yǔ)言規(guī)范、特性和數(shù)據(jù)結(jié)構(gòu)的編碼方式,蘊(yùn)涵較為豐富,為了行文更順暢、容易理解,此文暫時(shí)用簡(jiǎn)潔、優(yōu)雅代替。-- EarlGrey@編程派

原文鏈接:Trey Hunner,發(fā)布于11月9日。
譯文鏈接:編程派

有時(shí)候,利用Python語(yǔ)言簡(jiǎn)潔、優(yōu)雅地解決問(wèn)題的方法,會(huì)隨著時(shí)間變化。隨著Python不斷進(jìn)化,統(tǒng)計(jì)列表元素?cái)?shù)量的方法也在改變。

以計(jì)算元素在列表中出現(xiàn)的次數(shù)為例,我們可以編寫(xiě)出許多不同的實(shí)現(xiàn)方法。在分析這些方法時(shí),我們先不關(guān)注性能,只考慮代碼風(fēng)格。

要理解這些不同的實(shí)現(xiàn)方式,我們得先知道一些歷史背景。幸運(yùn)的是,我們生活在"__future__"世界,擁有一臺(tái)時(shí)間機(jī)器。接下來(lái),我們一起坐上時(shí)光機(jī),回到1997年吧。

if 語(yǔ)句

1997年1月1日,我們使用的是Python 1.4?,F(xiàn)在有一個(gè)不同顏色組成的列表,我們想知道列表里每種顏色出現(xiàn)的次數(shù)。我們用字典來(lái)計(jì)算吧!

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = {}
for c in colors:
    if color_counts.has_key(c):
        color_counts[c] = color_counts[c] + 1
    else:
        color_counts[c] = 1

注意:我們沒(méi)有使用+=,因?yàn)樵隽抠x值直到Python 2.0才出現(xiàn);另外,我們也沒(méi)有使用c in color_counts這個(gè)慣用法(idiom),因?yàn)檫@也是Python 2.2中才發(fā)明的,

運(yùn)行上述代碼之后,我們會(huì)發(fā)現(xiàn)color_counts字典里,現(xiàn)在包含了列表中每種顏色的出現(xiàn)次數(shù)。

color_counts
{"brown": 3, "yellow": 2, "green": 1, "black": 1, "red": 1}

上面的實(shí)現(xiàn)很簡(jiǎn)單。我們遍歷了每一種顏色,并判斷該顏色是否在字典中。如果不在,就在字典加入該顏色;如果在,就增加這種顏色的計(jì)數(shù)。

我們還可以把上面的代碼改寫(xiě)為:

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = {}
for c in colors:
    if not color_counts.has_key(c):
        color_counts[c] = 0
    color_counts[c] = color_counts[c] + 1

如果列表稀疏度高(即列表中不重復(fù)的顏色數(shù)量很多),這段代碼可能運(yùn)行的會(huì)有點(diǎn)慢。因?yàn)槲覀儸F(xiàn)在要執(zhí)行兩個(gè)語(yǔ)句,而不是一個(gè)。但是我們不關(guān)心性能問(wèn)題,我們只關(guān)注編碼風(fēng)格。經(jīng)過(guò)思考,我們決定采用新版的代碼。

try代碼塊(Code Block)

1997年1月2日,我們使用的還是Python 1.4。今早醒來(lái)的時(shí)候,我們突然意識(shí)到:我們的代碼遵循的是“三思而后行”(Look Before You Leap,即事先檢查每一種可能出現(xiàn)的情況)原則,但實(shí)際上我們應(yīng)該按照“獲得諒解比獲得許可容易”(Easier to Ask Forgiveness, Than Permission,即不檢查,出了問(wèn)題由異常處理來(lái)處理)的原則進(jìn)行編程,因?yàn)楹笳吒雍?jiǎn)潔、優(yōu)雅。我們用try-except代碼塊來(lái)重構(gòu)下代碼吧:

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = {}
for c in colors:
    try:
        color_counts[c] = color_counts[c] + 1
    except KeyError:
        color_counts[c] = 1

現(xiàn)在,我們的代碼嘗試增加每種顏色的計(jì)數(shù)。如果某顏色不在字典里,那么就會(huì)拋出KeyError,我們隨之將該顏色的計(jì)數(shù)設(shè)置為1。

get方法

1998年1月1日,我們已經(jīng)升級(jí)到了Python 1.5。我們決定重構(gòu)之前的代碼,使用字典中新增的get方法。

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = {}
for c in colors:
    color_counts[c] = color_counts.get(c, 0) + 1

現(xiàn)在,我們的代碼會(huì)遍歷每種顏色,從字典中獲取該顏色的當(dāng)前計(jì)數(shù)值。如果沒(méi)有這個(gè)計(jì)數(shù)值,則該顏色的計(jì)數(shù)值默認(rèn)為0,然后在數(shù)值的基礎(chǔ)上加1。最后將字典中相應(yīng)鍵的值設(shè)置為新的計(jì)數(shù)。

把主要代碼都寫(xiě)在一行里,感覺(jué)很酷,但是我們不敢完全肯定這種做法更加簡(jiǎn)潔、優(yōu)雅。我們覺(jué)得可能有點(diǎn)太聰敏了,所以還是撤銷(xiāo)了這次的重構(gòu)。

setdefault方法

2001年1月1日,我們現(xiàn)在使用的是Python 2.0。我們聽(tīng)說(shuō)字典類(lèi)型現(xiàn)在有一個(gè)setdefault方法,決定利用它重構(gòu)我們的代碼。我們還決定使用新增加的+=增量賦值運(yùn)算符。

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = {}
for c in colors:
    color_counts.setdefault(c, 0)
    color_counts[c] += 1

無(wú)論是否需要,我們?cè)诿恳淮窝h(huán)時(shí)都會(huì)調(diào)用setdefault方法。但這樣做,的確會(huì)讓代碼看上去可讀性更高。我們發(fā)現(xiàn)這種方法比之前的代碼更加簡(jiǎn)潔、優(yōu)雅,所以提交了此次修改。

fromkeys方法

2004年1月1日,我們使用的是Python 2.3。我們聽(tīng)說(shuō)字典新增了一個(gè)叫fromkeys的類(lèi)方法(class method),可以利用列表中的元素作為鍵來(lái)構(gòu)建字典。我們使用新方法重構(gòu)了代碼:

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = dict.fromkeys(colors, 0)
for c in colors:
    color_counts[c] += 1

這段代碼將不同的顏色作為鍵,創(chuàng)建了一個(gè)新的字典,每個(gè)鍵的值被默認(rèn)設(shè)置為0。這樣,我們?cè)黾用總€(gè)鍵的值時(shí),就不用擔(dān)心是否已經(jīng)進(jìn)行了設(shè)置。我們也不需要在代碼中進(jìn)行檢查或異常處理了,這看上去是個(gè)改進(jìn)。我們決定就這樣修改代碼。

推導(dǎo)式(Comprehension)與集合

2005年1月1日,我們現(xiàn)在用的是Python 2.4。我們發(fā)現(xiàn)可以利用集合(Python 2.3中發(fā)布,2.4版成為內(nèi)置類(lèi)型)與列表推導(dǎo)式(Python 2.0中發(fā)布)來(lái)解決計(jì)數(shù)問(wèn)題。進(jìn)一步思考之后,我想起來(lái)Python 2.4中還發(fā)布了生成器表達(dá)式(generator expressions),我們最后決定不用列表推導(dǎo)式,而是采用生成器表達(dá)式。

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = dict((c, colors.count(c)) for c in set(colors))

注意:我們這里使用的不是字典推導(dǎo)式,因?yàn)樽值渫茖?dǎo)式直到Python 2.7才被發(fā)明。

運(yùn)行成功了,而且只有一行代碼。但是這種代碼夠簡(jiǎn)潔、優(yōu)雅嗎 ?

我們想起了Python之禪(Zen of Python),這個(gè)Python編程指導(dǎo)原則起源于一個(gè)Python郵件列表,并悄悄地收進(jìn)了Python 2.2.1版本中。我們?cè)赗EPL(read-eval-print loop,交互式解釋器)界面中輸入import this

import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly. # 優(yōu)美勝過(guò)丑陋
Explicit is better than implicit. # 明確勝過(guò)含蓄
Simple is better than complex. # 簡(jiǎn)單勝過(guò)復(fù)雜
Complex is better than complicated. # 復(fù)雜勝過(guò)難懂
Flat is better than nested. # 扁平勝過(guò)嵌套
Sparse is better than dense. # 稀疏勝過(guò)密集
Readability counts. # 易讀亦有價(jià)
Special cases aren"t special enough to break the rules. # 特例也不能特殊到打破規(guī)則
Although practicality beats purity. # 盡管實(shí)用會(huì)擊敗純潔
Errors should never pass silently. # 錯(cuò)誤永遠(yuǎn)不應(yīng)默默地溜掉 
Unless explicitly silenced. # 除非明確地使其沉默
In the face of ambiguity, refuse the temptation to guess.  # 面對(duì)著不確定,要拒絕猜測(cè)的誘惑
There should be one-- and preferably only one --obvious way to do it.  # 應(yīng)該有一個(gè)–寧肯只有一個(gè)–明顯的實(shí)現(xiàn)方法
Although that way may not be obvious at first unless you"re Dutch. # 也許這個(gè)方法開(kāi)始不是很明顯,除非你是荷蘭人
Now is better than never. #現(xiàn)在做也要?jiǎng)龠^(guò)不去做
Although never is often better than right now. # 盡管不做通常好過(guò)立刻做
If the implementation is hard to explain, it"s a bad idea. # 如果實(shí)現(xiàn)很難解釋?zhuān)撬褪且粋€(gè)壞想法
If the implementation is easy to explain, it may be a good idea. # 如果實(shí)現(xiàn)容易解釋?zhuān)撬赡芫褪且粋€(gè)好想法
Namespaces are one honking great idea -- let"s do more of those! # 命名空間是一個(gè)響亮的出色想法–就讓我們多用用它們

譯者注:Python之禪的翻譯版本很多,這里選用的譯文出自啄木鳥(niǎo)社區(qū)。

我們的代碼變得更復(fù)雜,時(shí)間復(fù)雜度從O(n)增加到了O(n2);還變的更丑,可讀性更差了。我們那樣改,是一次有趣的嘗試,但是一行代碼的實(shí)現(xiàn)形式,沒(méi)有我們之前的方法簡(jiǎn)潔、優(yōu)雅。我們最后還是決定撤銷(xiāo)修改。

defaultdict方法

2007年1月1日,我們使用的是Python 2.5。我們剛發(fā)現(xiàn),defaultdict已經(jīng)被加入標(biāo)準(zhǔn)庫(kù)。這樣,我們就可以把字典的默認(rèn)鍵值設(shè)置為0了。讓我們使用defaultdict重構(gòu)代碼:

from collections import defaultdict
    colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
    color_counts = defaultdict(int)
    for c in colors:
        color_counts[c] += 1

那個(gè)for循環(huán)現(xiàn)在變得真簡(jiǎn)單!這樣肯定是更加簡(jiǎn)潔、優(yōu)雅了。

我們發(fā)現(xiàn),color_counts這個(gè)變量的行為現(xiàn)在有點(diǎn)不同,但是它的確繼承了字典的特性,支持所有相同的映射功能。

color_counts
defaultdict(, {"brown": 3, "yellow": 2, "green": 1, "black": 1, "red": 1})

我們?cè)谶@里沒(méi)有把color_counts轉(zhuǎn)換成字典,而是假設(shè)其他的代碼也使用鴨子類(lèi)型(duck typing, Python中動(dòng)態(tài)類(lèi)型的一種,這里的意思是:其他代碼會(huì)將color_counts視作字典類(lèi)型),不再改動(dòng)這個(gè)類(lèi)似字典的對(duì)象。

Counter類(lèi)

2011年1月1日,我們使用的是Python 2.7。別人告訴我們,之前使用defaultdict編寫(xiě)的代碼,不再是統(tǒng)計(jì)顏色出現(xiàn)次數(shù)最簡(jiǎn)潔、優(yōu)雅的方法了。Python 2.7中新引入了一個(gè)Counter類(lèi),可以完全解決我們的問(wèn)題。

from collections import Counter
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"]
color_counts = Counter(colors)

還有比這更簡(jiǎn)單的方法嗎?這個(gè)一定是最簡(jiǎn)潔、優(yōu)雅的實(shí)現(xiàn)了。

defaultdict一樣,Counter類(lèi)返回的也是一個(gè)類(lèi)似字典的對(duì)象(實(shí)際是字典的一個(gè)子類(lèi))。這對(duì)滿足我們的需求來(lái)說(shuō)足夠了,所以我們就這么干了。

color_counts
Counter({"brown": 3, "yellow": 2, "green": 1, "black": 1, "red": 1})
性能考慮

請(qǐng)注意,在編寫(xiě)這些實(shí)現(xiàn)方式時(shí),我們都沒(méi)有關(guān)注效率問(wèn)題。大部分方法的時(shí)間復(fù)雜度相同(O(n)),但是不同的Python語(yǔ)言實(shí)現(xiàn)形式(如CPython, PyPy,或者Jython)下,運(yùn)行時(shí)間會(huì)有差異。

盡管性能不是我們的主要關(guān)注點(diǎn),我還是在CPython 3.5.0的實(shí)現(xiàn)下測(cè)試了運(yùn)行時(shí)間。從中,你會(huì)發(fā)現(xiàn)一個(gè)有趣的現(xiàn)象:隨著列表中顏色元素的密度(即相同元素的數(shù)量)變化,每一種實(shí)現(xiàn)方法的相對(duì)效率也會(huì)不同。

結(jié)語(yǔ)

根據(jù)Python之禪,“ 應(yīng)該有一個(gè)——寧肯只有一個(gè)明顯的實(shí)現(xiàn)方法”。這句話所說(shuō)的狀態(tài)值得追求,但事實(shí)是,并不總是只有一種明顯的方法。這個(gè)“明顯”的方法會(huì)隨著時(shí)間、需求和專(zhuān)業(yè)水平,不斷地變化。

“簡(jiǎn)潔、優(yōu)雅”(即Pythonic)也是一個(gè)相對(duì)的概念。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44193.html

相關(guān)文章

  • Python 學(xué)習(xí)資料整理

    摘要:整理可愛(ài)的簡(jiǎn)化元編程的是什么鬼,多線程性能究竟如何淺談的語(yǔ)句基礎(chǔ)深入理解中的賦值引用拷貝作用域命名空間和作用域窺探引用計(jì)數(shù)編寫(xiě)漂亮的,可讀的代碼的最佳時(shí)間語(yǔ)言中計(jì)數(shù)方法的演變描述符解密的內(nèi)存管理機(jī)制深入的內(nèi)存管理源碼剖析 Python 整理 Python3 Official Documentation Python3 Document Coding Style PEP 8 Encodi...

    pf_miles 評(píng)論0 收藏0
  • 細(xì)數(shù)Python三十年技術(shù)演變史——萌發(fā)于小眾,崛起于AI

    摘要:作者宋天龍來(lái)源科技大本營(yíng)導(dǎo)語(yǔ)一切都始于年的那個(gè)圣誕節(jié),的誕生并不算恰逢其時(shí),它崛起充滿了機(jī)遇巧合,也有其必然性。年的圣誕節(jié),開(kāi)始編寫(xiě)語(yǔ)言的編譯器。年發(fā)布的標(biāo)志著的框架基本確定。年月發(fā)布了系列的最后一個(gè)版本,主版本號(hào)為。 showImg(https://segmentfault.com/img/remote/1460000019862276); 作者 | 宋天龍來(lái)源 | AI科技大本營(yíng) ...

    tuniutech 評(píng)論0 收藏0
  • 能讓你更早下班Python垃圾回收機(jī)制

    摘要:內(nèi)部通過(guò)引用計(jì)數(shù)機(jī)制來(lái)統(tǒng)計(jì)一個(gè)對(duì)象被引用的次數(shù)。下一步,就該被我們的垃圾回收器給收走了。而我們垃圾回收機(jī)制只有當(dāng)引用計(jì)數(shù)為的時(shí)候才會(huì)釋放對(duì)象。以空間換時(shí)間的方法提高垃圾回收效率。 人生苦短,只談風(fēng)月,談什么垃圾回收。據(jù)說(shuō)上圖是某語(yǔ)言的垃圾回收機(jī)制。。。我們寫(xiě)過(guò)C語(yǔ)言、C++的朋友都知道,我們的C語(yǔ)言是沒(méi)有垃圾回...

    pumpkin9 評(píng)論0 收藏0
  • looking at python

    摘要:代碼易于閱讀,并且,易于維護(hù)這一條是看來(lái)的,這可能只是一種感覺(jué)問(wèn)題。因此的垃圾回收機(jī)制由一個(gè)引用計(jì)數(shù)器和一個(gè)循環(huán)垃圾收集器組成。類(lèi)的繼承支持多重繼承父類(lèi)的構(gòu)造函數(shù)必須在子類(lèi)中親自調(diào)用 Python 初探 Python是。。? python是一種解釋型腳本語(yǔ)言。 python語(yǔ)言是一句一句執(zhí)行的,可以再命令提示符中直接編寫(xiě)程序并隨時(shí)獲得結(jié)果 python支持面向?qū)ο? 我已經(jīng)會(huì)c了,除...

    Channe 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<