国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

編程語(yǔ)言之問(wèn):何時(shí)該借用,何時(shí)該創(chuàng)造?

spademan / 2174人閱讀

摘要:普通可迭代對(duì)象只有魔術(shù)方法,而不像迭代器一樣擁有魔術(shù)方法,這意味著它無(wú)法實(shí)現(xiàn)自遍歷過(guò)程,同時(shí)在經(jīng)過(guò)循環(huán)的它遍歷后,也不會(huì)破壞原有的結(jié)構(gòu)。這兩個(gè)是我創(chuàng)造的概念,詳見(jiàn)進(jìn)階迭代器與迭代器切片。

本文原創(chuàng)并首發(fā)于公眾號(hào)【Python貓】,未經(jīng)授權(quán),請(qǐng)勿轉(zhuǎn)載。

原文地址:https://mp.weixin.qq.com/s/Oy...

6 月 22 日,Python 之父 Guido 發(fā)了一條推特,說(shuō)了 Python 的一則歷史故事,他說(shuō) elif 是從 C 語(yǔ)言中偷過(guò)來(lái)的:

elif 是“else if”的簡(jiǎn)寫,用于條件判斷。當(dāng)只有兩個(gè)分支時(shí),我們會(huì)寫成“if...else...”,當(dāng)出現(xiàn)更多分支時(shí),我們會(huì)寫成如下格式:

if 判斷條件1:
    做事情1
elif 判斷條件2:
    做事情2
else:
    做其它事

簡(jiǎn)寫而成的 elif 不僅是減少了幾個(gè)字符,而且由于單一而清晰的用途,它還不會(huì)給我們帶來(lái)理解或使用上的困惑。

但是,簡(jiǎn)寫法并不是主流,完整寫法才是主流,C 語(yǔ)言中就是采用完整的寫法:

if(判斷條件1)
{
   做事情1
}
else if(判斷條件2)
{
   做事情2
}
else 
{
   做其它事
}

沒(méi)錯(cuò),C 語(yǔ)言使用的是全拼寫法,但是在它的預(yù)處理/預(yù)編譯語(yǔ)句中,還有一個(gè) elif 指令,Guido 所說(shuō)的“偷”,就是從這來(lái)的:

#if 常量表達(dá)式1
// 編譯1
#elif 常量表達(dá)式2
// 編譯2
#else
// 編譯3
#endif

Python 沒(méi)有預(yù)編譯,所以所謂的偷,跟預(yù)編譯沒(méi)有關(guān)系,只是在對(duì)比兩種寫法后,借用了更簡(jiǎn)潔的寫法而已。

為什么 C 語(yǔ)言不把兩種寫法統(tǒng)一起來(lái)呢?這我不得而知了,而 Guido 在兩種寫法中,選擇了后一種非主流卻更好用的寫法。我想對(duì)他說(shuō),你“偷”得好??!

實(shí)際上,留言區(qū)里的人也有同感,紛紛表示:不介意、很 okay、非常喜歡,還有人說(shuō)“不是偷,而是收獲(harvested)”、“不是偷,而是把它提升了一些高度”……

前不久,我寫了一篇《聊聊 print 的前世今生》,print 這個(gè)詞就是從 C 語(yǔ)言中借用來(lái)的。除此之外,如果有人仔細(xì)比較這兩種語(yǔ)言的關(guān)鍵字和習(xí)慣命名,肯定會(huì)發(fā)現(xiàn)不少相同的內(nèi)容。

編程語(yǔ)言間有一些共享的元素,這很常見(jiàn),創(chuàng)造一門語(yǔ)言并不意味著要原創(chuàng)每一個(gè)詞句,畢竟大部分思想是共通的,作為基礎(chǔ)設(shè)施的詞語(yǔ)更是如此。

那么,我突然好奇了:創(chuàng)造一門編程語(yǔ)言時(shí),什么時(shí)候該借用,什么時(shí)候該創(chuàng)造呢?

這個(gè)問(wèn)題看起來(lái)可能沒(méi)啥意義,因?yàn)榻K其一生,我們多數(shù)人也不大可能會(huì)參與創(chuàng)造一門編程語(yǔ)言。

但我覺(jué)得它還是極有意義的,首先,提問(wèn)精神值得肯定,其次,它還提供了一種溯源、甄別、遴選、創(chuàng)造的體系性視角,我認(rèn)為這是求知的正確思維方式。

帶著這個(gè)疑惑,我特別想要考察的是 Python 的 for 循環(huán)。

如果你有其它語(yǔ)言基礎(chǔ),就知道 “for 循環(huán)”通常指的是這樣的三段式結(jié)構(gòu):

for ( init; condition; increment ){
   statement(s);
}

// java
for(int x = 10; x < 20; x = x+1) {
    System.out.print("value of x : " + x );
    System.out.print("
");
}

這種 C 風(fēng)格的寫法是很初級(jí)的東西,不少語(yǔ)言都借用了。但是,它的寫法實(shí)在繁瑣,為了更方便地遍歷集合中的元素,人們?cè)?for 循環(huán)之外又引入了升級(jí)版的 foreach 循環(huán):

// java
int[] a = {1,2,3};
for(int i : a){
    System.out.print(i + ",");
}

// C#
int[] a = {1,2,3};
foreach(int i in a){
    System.Console.WriteLine(i);
}

Python 中也有 for 循環(huán),但是,它借用有度,在設(shè)計(jì)上早早就有自己獨(dú)到的考慮,它直接摒棄了三段式的 for 循環(huán),而是采用類似 foreach 的一種寫法:

for iterating_var in sequence:
   statements(s)

# 例子
for i in range(3):
    print(i)

for i in "hello":
    print(i)

從表面上看,Python 的 for 循環(huán)跟其它語(yǔ)言的 foreach 很相似,但實(shí)際上,它的工作原理卻很不相同。

為什么會(huì)有不同呢?主要是因?yàn)?Python 的 for 語(yǔ)句用于可迭代對(duì)象上,而不僅僅是用于集合或者普通的容器(雖然它們也是可迭代對(duì)象),而可迭代對(duì)象還可再細(xì)分出迭代器與生成器,這會(huì)造成最終結(jié)果的極大差異。

先看看兩個(gè)例子:

# 例1,普通可迭代對(duì)象
x = [1, 2, 3]
for i in x:
    print(i)
for i in x:
    print(i)

# 例2,迭代器或生成器
y = iter([1, 2, 3])
# y = (i for i in [1,2,3])
for i in y:
    print(i)
for i in y:
    print(i)

例 1 中,“1 2 3”會(huì)被打印兩次,而在例 2 中,則只會(huì)打印一次。

普通可迭代對(duì)象只有 __iter__() 魔術(shù)方法,而不像迭代器一樣擁有 __next__() 魔術(shù)方法,這意味著它無(wú)法實(shí)現(xiàn) 自遍歷 過(guò)程,同時(shí)在經(jīng)過(guò) for 循環(huán)的 它遍歷 后,也不會(huì)破壞原有的結(jié)構(gòu)。(這兩個(gè)是我創(chuàng)造的概念,詳見(jiàn)《Python進(jìn)階:迭代器與迭代器切片》)。

但是,迭代器是一種匱乏的設(shè)計(jì),具有單向損耗的特性,遍歷一次后就會(huì)被破壞掉,不能重復(fù)利用。(關(guān)于迭代器的設(shè)計(jì)問(wèn)題,這篇文章值得一看《當(dāng)談?wù)摰鲿r(shí),我談些什么?》)。

這表明了,Python 中 for 循環(huán)的使用場(chǎng)景很廣闊,而且它還可能帶來(lái)非純結(jié)果,即重復(fù)執(zhí)行同樣的代碼塊,會(huì)出現(xiàn)不同的結(jié)果。

這是不是跟別的語(yǔ)言很不同了呢?相同的關(guān)鍵字,相似的循環(huán)思想與寫法,但是,帶來(lái)的影響卻有差別。

關(guān)于 Python 的 for 循環(huán),還有一個(gè)很獨(dú)特的設(shè)計(jì),即 for-else 結(jié)構(gòu):

x = [1, 2, 3]
for i in x:
    print(i, end = " ")
else:
    print("ok")

# 輸出:1 2 3 ok

本文開頭提到了 if-else 結(jié)構(gòu),只有在不滿足 if 條件時(shí),才會(huì)執(zhí)行到 else 部分,也就是說(shuō),如果 if 語(yǔ)句為真,那執(zhí)行完它的語(yǔ)句塊后,就會(huì)跳過(guò) else 部分。

這是一種非此即彼的并行關(guān)系 ,直白地說(shuō)是“如果...就...;否則就...” 。

但是,對(duì)于 for-else 結(jié)構(gòu),for 語(yǔ)句并不是在做真值判斷,它的程序體必然會(huì)執(zhí)行(除非可迭代對(duì)象為空),執(zhí)行后還會(huì)繼續(xù)執(zhí)行 else 部分。

所以,它是一種先此后彼的串行關(guān)系 ,翻譯出來(lái)則是“對(duì)于...就...;然后...”。

這種結(jié)構(gòu)肯定不是從 C 語(yǔ)言中借用來(lái)的,至于是否為 Python 所獨(dú)創(chuàng),我不確定(大概率是,姑且認(rèn)為是吧),如果有知情的同學(xué),煩請(qǐng)告知。

那么,為什么 Python 要加上這種設(shè)計(jì)呢,它有什么實(shí)際的用途么?

x = [1,2,3]
for i in x:
    if i % 2 == 0:
        print(i)   # match
        break
else:
    print("mismatch")

上例的 for 部分增加了一個(gè)判斷以及 break,這個(gè) break 不僅會(huì)跳出 for 循環(huán)本身,還會(huì)跳過(guò) else 部分。

上例的作用是查找偶數(shù),如果找到則打印出來(lái),如果 for 循環(huán)遍歷完都找不到,則進(jìn)入到 else 分支,打印“mismatch”的結(jié)果。

所以,其實(shí) else 是 for 循環(huán)有沒(méi)有正常遍歷結(jié)束的標(biāo)記,如果在循環(huán)后沒(méi)有達(dá)到某種目標(biāo)而跳出(break、return 或者 raise),就可以在 else 中做必要的補(bǔ)充(記錄日志、拋出異常等等)。

這種設(shè)計(jì)并不算一個(gè)好的設(shè)計(jì),因?yàn)?else 會(huì)帶來(lái)誤解(if-else 那種非此即彼的關(guān)系),而且它的最大用途需要結(jié)合 break 等跳出循環(huán)的操作,但是這層信息卻非顯而易見(jiàn)的。

在核心開發(fā)者的郵件列表里,就有不少爭(zhēng)論點(diǎn),2009 年的這封郵件梳理了大家的討論(https://mail.python.org/pipermail/python-ideas/2009-October/006155.html)。

其中,有開發(fā)者提議:

移除這個(gè)寫法

如果用了卻沒(méi)寫 break,就生成告警提示

替換 else 關(guān)鍵字(如 then、finally、else no break)

增加其它的功能

這封郵件一一列舉了這些觀點(diǎn)的提出原因及改進(jìn)想法,然后又一一地反駁了它們,最后的結(jié)論是保持 for-else 寫法不變,也就是大家現(xiàn)在看到的實(shí)現(xiàn)方式。它的完整語(yǔ)義是:

execute the for-loop (or while-loop)
if you reach a `break`, jump to the end of the `for...else` block
else execute the `else` suite

也就是說(shuō),else 對(duì)標(biāo)的是“是否執(zhí)行 break”,如果沒(méi)有 break,則進(jìn)入else。

但是,我并不認(rèn)可這種做法,因?yàn)?break 是隱含條件,在直觀上我們只看到了 for-else,很容易產(chǎn)生 if-else 那樣的聯(lián)想。因此,我反而贊同把 else 改為 then,以消除誤會(huì)。

這封郵件的反駁意見(jiàn)是,改成 then 會(huì)引入新的關(guān)鍵字,因此不好。

我認(rèn)為這個(gè)說(shuō)法有些牽強(qiáng)(從使用者的角度),還記得本文開頭的內(nèi)容么,elif 就是新引入的關(guān)鍵字啊,看看它現(xiàn)在是多受歡迎。

elif 屬于那種初看不知何意,但知道后肯定會(huì)記住的詞,而且也不大可能拼寫錯(cuò)誤。為了這點(diǎn)簡(jiǎn)潔易拼寫的好處,它就被引入成新的關(guān)鍵字了。

for-else 中的 else 屬于那種初看以為知道含義的詞,但實(shí)際卻表達(dá)著不同意思(準(zhǔn)確地說(shuō)是,由于不知道隱含條件,而造成的誤解),為了清晰語(yǔ)義的好處,我認(rèn)為可以引入新的關(guān)鍵詞 then 來(lái)替代 else。

不過(guò),我轉(zhuǎn)念一想,現(xiàn)在討論這個(gè)已經(jīng)沒(méi)有意義了,畢竟時(shí)間已經(jīng)過(guò)去了,那都是 10 年前的討論了。

如果在 Python 創(chuàng)造之初,或者在 Python 3 大版本改動(dòng)之初,這個(gè)討論就被提出,那很可能 for-else 會(huì)被設(shè)計(jì)成 for-then ,then 會(huì)像引入 elif 關(guān)鍵詞一樣被引入。

如果是那樣,說(shuō)不定 Guido 某天心血來(lái)潮說(shuō)起這則歷史小故事,留言區(qū)又會(huì)出現(xiàn)一大片的贊同之聲呢。

聊到這里,意猶未盡,但主題似乎有點(diǎn)跑偏,我們來(lái)稍微總結(jié)幾個(gè)要點(diǎn)吧:

Python 從 C 中借用了 elif,受到贊許

Python 沒(méi)有借用 C 傳統(tǒng)的三段式 for 循環(huán)

Python 采用類似 foreach 的表達(dá),但應(yīng)用范圍更廣

Python 的 for 循環(huán)由于迭代器的設(shè)計(jì)原因,會(huì)造成一些陷阱

Python 創(chuàng)造了 for-else 結(jié)構(gòu),它的隱含語(yǔ)義是 for-(if break)-else,曾有討論是否要?jiǎng)?chuàng)造新的關(guān)鍵詞替換 for-else,但是被否決了

本文談到的內(nèi)容很微小,好像沒(méi)有什么實(shí)際的幫助,不知道 elif 來(lái)源、不知道 for 循環(huán)的細(xì)節(jié)、不知道 for-else 的用途與爭(zhēng)論,這些統(tǒng)統(tǒng)都不會(huì)造成語(yǔ)言使用上的障礙。

但我還是那個(gè)觀點(diǎn):

閱讀 Python 的歷史,從中你可以看到設(shè)計(jì)者們對(duì)功能細(xì)節(jié)的打磨過(guò)程,最終你就明白了,Python 是如何一步一步地發(fā)展成今天的樣子。

這在我看來(lái)挺有趣的,更加增進(jìn)了我對(duì)于 Python 的了解,以后在編程到某些用法的時(shí)候,腦海里滿滿都是故事,它頓時(shí)也會(huì)變得立體生動(dòng)起來(lái)。

如果你讀后有所收獲,或者產(chǎn)生了不同想法,歡迎來(lái)知識(shí)星球與我互動(dòng)交流。

公眾號(hào)【Python貓】, 本號(hào)連載優(yōu)質(zhì)的系列文章,有喵星哲學(xué)貓系列、Python進(jìn)階系列、好書推薦系列、技術(shù)寫作、優(yōu)質(zhì)英文推薦與翻譯等等,歡迎關(guān)注哦。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/45063.html

相關(guān)文章

  • 從setTimeout-setInterval看JS線程

    摘要:提出標(biāo)準(zhǔn),允許腳本創(chuàng)建多個(gè)線程,但是子線程完全受主線程控制,且不得操作。所以,這個(gè)新標(biāo)準(zhǔn)并沒(méi)有改變單線程的本質(zhì)。事件循環(huán)主線程線程只會(huì)做一件事,就是從消息隊(duì)列里面取消息執(zhí)行消息,再取消息再執(zhí)行。工作線程是生產(chǎn)者,主線程是消費(fèi)者。 最近項(xiàng)目中遇到了一個(gè)場(chǎng)景,其實(shí)很常見(jiàn),就是定時(shí)獲取接口刷新數(shù)據(jù)。那么問(wèn)題來(lái)了,假設(shè)我設(shè)置的定時(shí)時(shí)間為1s,而數(shù)據(jù)接口返回大于1s,應(yīng)該用同步阻塞還是異步?我們...

    elliott_hu 評(píng)論0 收藏0
  • 使用python解釋設(shè)計(jì)模式[譯]

    摘要:最重要的是,任何設(shè)計(jì)模式都是一把雙刃劍。另一個(gè)設(shè)計(jì)模式是迭代器,在語(yǔ)言中以循環(huán)的形式實(shí)現(xiàn)。我們可以換個(gè)方法,利用策略模式和適配器模式的變種,能夠完美處理這種情景。何時(shí)使用它單例模式也許是最簡(jiǎn)單的設(shè)計(jì)模式了。 使用python解釋設(shè)計(jì)模式 原文地址有沒(méi)有好奇過(guò)設(shè)計(jì)模式是什么呢?在這篇文章中,我們將了解為什么設(shè)計(jì)模式是重要的,同時(shí)也會(huì)給出一些python的例子,解釋為什么以及在什么時(shí)候使用...

    MadPecker 評(píng)論0 收藏0
  • 前端知識(shí)點(diǎn)總結(jié)——JS高級(jí)(持續(xù)更新中)

    摘要:前端知識(shí)點(diǎn)總結(jié)高級(jí)持續(xù)更新中字符串什么是連續(xù)存儲(chǔ)多個(gè)字符的字符數(shù)組相同下標(biāo)遍歷選取不同類型不同不通用所有字符串都無(wú)權(quán)修改原字符串,總是返回新字符串大小寫轉(zhuǎn)換統(tǒng)一轉(zhuǎn)大寫統(tǒng)一轉(zhuǎn)小寫何時(shí)不區(qū)分大小寫時(shí),都需要先轉(zhuǎn)為一致的大小寫,再比較。 前端知識(shí)點(diǎn)總結(jié)——JS高級(jí)(持續(xù)更新中) 1.字符串 什么是: 連續(xù)存儲(chǔ)多個(gè)字符的字符數(shù)組 相同: 1. 下標(biāo) 2. .length 3. 遍歷 4....

    wangzy2019 評(píng)論0 收藏0
  • 大數(shù)據(jù)可以應(yīng)用到那些領(lǐng)域?

    摘要:大數(shù)據(jù)應(yīng)用已廣泛深入我們生活的方方面面,涵蓋醫(yī)療交通金融教育體育零售等各行各業(yè)。百度大數(shù)據(jù)分析疾病分布情況。更多案例大數(shù)據(jù)數(shù)據(jù)挖掘在交通領(lǐng)域有哪些應(yīng)用教育領(lǐng)域應(yīng)用案例百度大腦人腦大數(shù)據(jù)押高考作文題。 大數(shù)據(jù)應(yīng)用已廣泛深入我們生活的方方面面,涵蓋醫(yī)療、交通、金融、教育、體育、零售等各行各業(yè)。 天氣預(yù)測(cè)應(yīng)用案例: 典型的案例即天氣預(yù)測(cè)。各類氣象指征瞬時(shí)發(fā)生,以典型的高頻復(fù)雜的形式出現(xiàn),給各...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<