摘要:被公認(rèn)是一種新手友好型的語言,這種說法能夠成立,內(nèi)置函數(shù)在其中起到了極關(guān)鍵的作用。除了求長度,的某些內(nèi)置函數(shù)也能在中找到對應(yīng)的表達(dá)。的內(nèi)置函數(shù)不與特定的類綁定,它們是一級對象。以此類比,的內(nèi)置函數(shù)雖有簡便之美,但卻丟失了某些表意功能。
內(nèi)置函數(shù)是 Python 的一大特色,用極簡的語法實(shí)現(xiàn)很多常用的操作。
它們預(yù)先定義在內(nèi)置命名空間中,開箱即用,所見即所得。Python 被公認(rèn)是一種新手友好型的語言,這種說法能夠成立,內(nèi)置函數(shù)在其中起到了極關(guān)鍵的作用。
舉個例子,求字符串 x 的長度,Python 的寫法是 len(x) ,而且這種寫法對列表、元組和字典等對象也同樣適用,只需要傳入對應(yīng)的參數(shù)即可。len() 函數(shù)是共用的。
這是一種極簡哲學(xué)的體現(xiàn):Simple is better than complex。
但是,有些語言并不是這樣,例如在 Java 中,字符串類有一個求長度的方法,其它類也有自己的求長度的方法,它們無法共用。每次使用時,通過類或?qū)嵗齺碚{(diào)用。
同樣是求字符串長度,Python 的寫法:
saying = "Hello world!" print(len(saying)) # 結(jié)果:12
而在 Java 中,寫法可能如下(簡化起見):
String saying = "Hello world!"; System.out.println(saying.length()); // 結(jié)果:12
Python 采用的是一種前綴表達(dá)式 ,而 Java 采用的則是后綴表達(dá)式 。
除了求長度,Python 的某些內(nèi)置函數(shù)也能在 Java 中找到對應(yīng)的表達(dá)。例如,數(shù)值型字符串 s 轉(zhuǎn)化為整型數(shù)字,Python 可以用 int(s) 函數(shù),而 Java 可以用 Integer.parseInt(s) ;整型數(shù)字轉(zhuǎn)化為字符串,Python 可以用 str(i) ,而 Java 也有 String.valueOf(i) 。
Python 的內(nèi)置函數(shù)不與特定的類綁定,它們是一級對象。而 Java 的“函數(shù)”則無法脫離類而存在,它們只是附屬品。
從直觀角度來看,Python 的表達(dá)似乎是更優(yōu)的。但是,它們并不具有可比性 ,因為這是兩套語言系統(tǒng),各有獨(dú)特的范疇背景,并不能輕易地化約。
就好比是,不能因為拉丁字母筆畫簡單,就說它優(yōu)于漢字,因為在表意時,字母(表音文字)是遠(yuǎn)遜于漢字(表意文字)的。同樣的,日本借用了漢字的偏旁部首而造出來的文字,雖然更省筆墨,但是也完全喪失了意蘊(yùn)。
以此類比,Python 的內(nèi)置函數(shù)雖有簡便之美,但卻丟失了某些表意功能。有些人在質(zhì)疑/抨擊 Python 的時候,也喜歡拿這點(diǎn)說事,認(rèn)為這是 Python 的設(shè)計缺陷。
這就引出本文最想討論的一個問題來:為什么 Python 要設(shè)計成 len(x) 這種前綴表達(dá),而不是 x.len() 這樣的后綴表達(dá)呢?
事實(shí)上,后綴設(shè)計也是可行的,以 Python 中列表的兩個方法為例:
mylist = [2, 1, 3, 5, 4] mylist.sort() print(mylist) # [1, 2, 3, 4, 5] mylist.reverse() print(mylist) # [5, 4, 3, 2, 1]
它們都是通過列表對象來調(diào)用,并不是憑空從內(nèi)置命名空間中拿來的。語義表達(dá)得也很清楚,就是對 mylist 做排序和逆轉(zhuǎn)。
恰恰那么巧,它們還有兩個同父異母的兄弟 sorted() 與 reversed(),這倆是前綴表達(dá)型。
mylist = [2, 1, 3, 5, 4] sort_list = sorted(mylist) print(sort_list) # [1, 2, 3, 4, 5] reverse_list = reversed(mylist) print(list(reverse_list)) # [4, 5, 3, 1, 2]
不同的寫法,都在做同一件事(不考慮它們的副作用)。因此,后綴語法并非不可行,之所以不用,那肯定是刻意的設(shè)計。
回到前面的問題:為什么是 len(x) ,而不是 x.len(x),這根源于 Python 的什么設(shè)計思想呢?
Python 之父 Guido van Rossum 曾經(jīng)解釋過這個問題(鏈接見文末),有兩個原因:
對于某些操作,前綴符比后綴更好讀——前綴(和中綴)表示法在數(shù)學(xué)中有著悠久的歷史,其視覺效果有助于數(shù)學(xué)家思考問題。我們可以簡單地把公式 x*(a + b) 重寫成 x*a + x*b ,但同樣的事,以原生的面向?qū)ο蟮姆绞綄?shí)現(xiàn),就比較笨拙。
當(dāng)讀到 len(x) 時,我就 知道 這是在求某對象的長度。它告訴我了兩點(diǎn):返回值是一個整數(shù),參數(shù)是某種容器。但當(dāng)讀到 x.len() 時,我必須事先知道某種容器 x,它實(shí)現(xiàn)了一個接口,或者繼承了一個擁有標(biāo)準(zhǔn) len() 方法的類。我們經(jīng)常會目睹到這種混亂:一個類并沒有實(shí)現(xiàn)映射(mapping)接口,卻擁有 get() 或 keys() 方法,或者某些非文件對象,卻擁有一個 write() 方法。
解釋完這兩個原因之后,Guido 還總結(jié)成一句話說:“I see "len" as a built-in operation ”。這已經(jīng)不僅是在說 len() 更可讀易懂了,而完全是在拔高 len() 的地位。
這就好比說,分?jǐn)?shù) ? 中的橫線是數(shù)學(xué)中的一個“內(nèi)置”表達(dá)式,并不需要再實(shí)現(xiàn)什么接口之類的,它自身已經(jīng)表明了“某數(shù)除以某數(shù) ”的意思。不同類型的數(shù)(整數(shù)、浮點(diǎn)數(shù)、有理數(shù)、無理數(shù)...)共用同一個操作符,不必為每類數(shù)據(jù)實(shí)現(xiàn)一種求分?jǐn)?shù)的操作。
優(yōu)雅易懂是 Python 奉行的設(shè)計哲學(xué) ,len() 函數(shù)的前綴表達(dá)方式是最好的體現(xiàn)。我想起在《超強(qiáng)匯總:學(xué)習(xí)Python列表,只需這篇文章就夠了》這篇文章中,曾引述過 Guido 對“為什么索引從 0 開始 ”的解釋。其最重要的原因,也正是 0-based 索引最優(yōu)雅易懂。
讓我們來先看看切片的用法。可能最常見的用法,就是“取前 n 位元素”或“從第i 位索引起,取后 n 位元素”(前一種用法,實(shí)際上是 i == 起始位的特殊用法)。如果這兩種用法實(shí)現(xiàn)時可以不在表達(dá)式中出現(xiàn)難看的 +1 或 -1,那將會非常的優(yōu)雅。使用 0-based 的索引方式、半開區(qū)間切片和缺省匹配區(qū)間的話(Python最終采用這樣的方式),上面兩種情形的切片語法就變得非常漂亮:a[:n] 和 a[i:i+n],前者是 a[0:n] 的縮略寫法。
所以,我們能說 len(x) 擊敗 x.len() ,支撐它的是一種化繁為簡、純粹卻深邃的設(shè)計思想。
面向?qū)ο蟮木幊陶Z言自發(fā)明時起,就想模擬我們生活于其中的現(xiàn)實(shí)世界。可是什么類啊、接口啊、對象啊、以及它們的方法啊,這些玩意的毒,有時候蒙蔽了我們?nèi)タ匆娛澜绫举|(zhì)的眼睛。
桌子類有桌子類的求長度方法,椅子類有椅子類的求長度方法,無窮無盡,可現(xiàn)實(shí)真是如此么?求長度的方法就不能是一種獨(dú)立存在的對象么?它之所以存在,是因為有“對象”存在,而不是因為有某個類才存在啊。
所以,我想說,len(x) 擊敗 x.len(),這還體現(xiàn)了 Python 對世界本質(zhì)的洞察 。
求某個對象的長度,這種操作獨(dú)立于對象之外而存在,并不是該對象內(nèi)部所有的一種屬性或功能。從這個角度理解,我們能夠明白,為什么 Python 要設(shè)計出內(nèi)置函數(shù)? 內(nèi)置函數(shù)其實(shí)是對世界本質(zhì)的一種捕捉。
這些見微知著的發(fā)現(xiàn),足夠使我們愛上這門語言了。人生苦短,我用 Python。
關(guān)聯(lián)閱讀:
Guido 解釋 len 的由來:http://suo.im/4ImAEo
Guido 解釋 0 索引的由來:http://suo.im/5cr12S
本文原創(chuàng)并首發(fā)于公眾號【Python貓】,未經(jīng)授權(quán),請勿轉(zhuǎn)載。
原文地址:https://mp.weixin.qq.com/s/pK...
公眾號【Python貓】, 本號連載優(yōu)質(zhì)的系列文章,有喵星哲學(xué)貓系列、Python進(jìn)階系列、好書推薦系列、技術(shù)寫作、優(yōu)質(zhì)英文推薦與翻譯等等,歡迎關(guān)注哦。后臺回復(fù)“愛學(xué)習(xí)”,免費(fèi)獲得一份學(xué)習(xí)大禮包。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/74226.html
摘要:被公認(rèn)是一種新手友好型的語言,這種說法能夠成立,內(nèi)置函數(shù)在其中起到了極關(guān)鍵的作用。除了求長度,的某些內(nèi)置函數(shù)也能在中找到對應(yīng)的表達(dá)。的內(nèi)置函數(shù)不與特定的類綁定,它們是一級對象。以此類比,的內(nèi)置函數(shù)雖有簡便之美,但卻丟失了某些表意功能。 showImg(https://segmentfault.com/img/remote/1460000018939150); 內(nèi)置函數(shù)是 Python ...
摘要:與純占位符相對應(yīng),非純占位符的切片是非空列表,對它進(jìn)行操作賦值與刪除,將會影響原始列表。迭代器是中獨(dú)特的一種高級對象,它本身不具備切片功能,然而若能將它用于切片,這便仿佛是錦上添花,能達(dá)到如虎添翼的效果。 showImg(https://segmentfault.com/img/bVblTuC?w=4288&h=2287); 導(dǎo)讀:切片系列文章連續(xù)寫了三篇,本文是對它們做的匯總。為什么...
閱讀 2983·2021-10-19 11:46
閱讀 978·2021-08-03 14:03
閱讀 2934·2021-06-11 18:08
閱讀 2904·2019-08-29 13:52
閱讀 2743·2019-08-29 12:49
閱讀 479·2019-08-26 13:56
閱讀 923·2019-08-26 13:41
閱讀 848·2019-08-26 13:35