<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          吐槽:Python正在從簡明轉(zhuǎn)向臃腫!

          共 5873字,需瀏覽 12分鐘

           ·

          2021-01-04 20:57

          作者 |?天元浪子
          來源 |?Python作業(yè)輔導(dǎo)員

          國慶長假期間,Python3.9正式推出,各大IT平臺和眾多自媒體紛紛火力全開,熱推Python3.9的新增特性。然而,除了媒體的自娛自樂,幾乎所有的程序員都對此表示無感。我甚至覺得 ,每一次的版本升級都是在抬升Python的學(xué)習(xí)門檻,令初學(xué)者望而生畏。

          簡單和優(yōu)雅,是Python創(chuàng)始人吉多 · 范羅蘇姆(龜叔)開立山門之時為Python確立的哲學(xué)理念?,F(xiàn)在,Pyton的發(fā)展顯然已經(jīng)背離了這一原則:不管有用無用,但凡別家有的,一概收入;不管是否適合,只要能充門面,悉數(shù)拿來。此情勢正如當(dāng)年P(guān)andas之父韋斯·麥金尼面對Pandas的快速擴(kuò)張時所表達(dá)出的無奈:“Pandas正在背離我最初所期望的簡潔和易用,變得越來越臃腫和不可控制?!?/span>

          曾經(jīng),我非常地喜歡Python。今天,這份愛依然在,但多了一些冷靜和理性。十幾年的陪伴,從默默無聞到炙手可熱,Python終于在軟件排行榜上占據(jù)了顯耀的位置。在席卷軟件行業(yè)的擴(kuò)張風(fēng)暴中,在Python連續(xù)不斷地版本升級中,我卻分明看到了一種危險(xiǎn)的轉(zhuǎn)變:Python正在從簡明轉(zhuǎn)向臃腫,從實(shí)用轉(zhuǎn)向媚俗。

          忍了很久,今日得閑,吐槽一下Python的新增語言特性。以下總結(jié)了導(dǎo)致Python危險(xiǎn)轉(zhuǎn)向的十大槽點(diǎn),排名不分先后。

          1. 媚俗的靜態(tài)類型檢查

          大約從Py3.5開始,直至最新的Py3.9,感覺Python語言項(xiàng)目團(tuán)隊(duì)就在做一件事兒:靜態(tài)類型檢查。為了實(shí)現(xiàn)類型檢查,他們推出了typing模塊,定義了一大堆的應(yīng)用規(guī)則。相應(yīng)的,有一批靜態(tài)類型檢查工具應(yīng)運(yùn)而生,比如Mypy、Pylint或者Pyflakes,PyCharm也可以很好地集成這些工具。對此,我只想說一句:Python是動態(tài)語言吧?既然是動態(tài)語言,那你檢查個毛線?即便檢查通過,就能像編譯語言那樣運(yùn)行了?一切不過是虛幻的假象而已,請別用其他語言的理念戕害質(zhì)樸的Python。Python追求的是用最簡捷的方式解決問題,而不是制造麻煩,然后再解決麻煩。Python強(qiáng)推靜態(tài)類型檢查,不過是迎合那些集成開發(fā)環(huán)境(IDE),同時滿足不明就里的程序員的成就感和虛榮心罷了。

          2. ?畫蛇添足的變量類型聲明

          當(dāng)一個擁有5年工作經(jīng)驗(yàn)的Python程序員讀到下面的代碼時,會有什么樣的感受呢?
          >>>?name:?str
          >>>?age:?int?=?18
          >>>?gilrfriends:?list?=?['奧黛麗·赫本',?'卡米拉·貝勒',?'安吉麗娜·朱莉']
          相信他一定會說,天哪,這是什么?是Python嗎?沒錯,這的確是Python??雌饋硐袷侵付俗兞康念愋停词瓜裣旅孢@樣用字符串給被指定為列表類型的變量賦值,運(yùn)行時也不會發(fā)出任何的提示或警告。
          >>>?gilrfriends:?list?=?'奧黛麗·赫本,?卡米拉·貝勒,?安吉麗娜·朱莉'?#?打著右轉(zhuǎn)燈左轉(zhuǎn)
          >>>?gilrfriends
          '奧黛麗·赫本,?卡米拉·貝勒,?安吉麗娜·朱莉'
          你看,打著右轉(zhuǎn)燈左轉(zhuǎn),照樣通行無誤。這樣畫蛇添足的操作有什么用呢?原來僅僅是為了讓IED或者類型檢查工具知道變量的類型。工具原本是為程序員服務(wù)的,現(xiàn)在好了,你得先為工具服務(wù)。差評!

          3. 雞肋般的函數(shù)及參數(shù)的類型注解

          我一直在尋找一種可以限定函數(shù)參數(shù)類型的方法,以避免程序運(yùn)行時出現(xiàn)意外的情況。受限于Python的機(jī)制,大多數(shù)情況下我只能使用斷言(assert)在函數(shù)內(nèi)部對參數(shù)類型作出限制,同時盡可能在doc中對參數(shù)類型及含義作詳盡描述,就像下面的代碼一樣。
          def?sphere(center,?radius,?color,?slices=90):
          ????"""繪制球體

          ????center??????-?球心坐標(biāo),長度為3的元組或列表
          ????radius??????-?半徑,浮點(diǎn)型
          ????color???????-?頂點(diǎn)顏色,字符串
          ????slices??????-?球面分片數(shù)(數(shù)值越大越精細(xì)),整型
          ????"""


          ????assert?isinstance(center,?(tuple,?list))?and?len(center)==3,?'期望參數(shù)center是長度為3的元組或列表'
          ????print('Hello')
          ????return?True????
          現(xiàn)在,如果按照Python指導(dǎo)委員會所倡導(dǎo)的方式,上面的代碼應(yīng)該寫成如下的樣式。
          from?typing?import?Union
          def?sphere(center:Union[tuple,list],?radius:float,?color:str,?slices:int=90)?->?bool:
          ????"""繪制球體

          ????center??????-?球心坐標(biāo),長度為3的元組或列表
          ????radius??????-?半徑,浮點(diǎn)型
          ????color???????-?頂點(diǎn)顏色,字符串
          ????slices??????-?球面分片數(shù)(數(shù)值越大越精細(xì)),整型
          ????"""


          ????print('Hello')
          ????return?True?????
          看上去一切都是完美的,但結(jié)果令人遺憾。這個函數(shù)及參數(shù)的類型注解只是一個注解而已,中看不中用:不管你輸入了什么類型的參數(shù),只要數(shù)量夠3個或者4個,就可以被執(zhí)行。唯一的作用就是降低了代碼的可讀性,原本四個參數(shù)一眼可見,現(xiàn)在卻要花費(fèi)20秒鐘來辨認(rèn)。不會有類型驗(yàn)證(除非使用類型檢查工具),更不會有長度檢查。如果想要這些功能,一切還得靠自己。

          4. 不加限制的擴(kuò)展運(yùn)算符

          任何一門編程語言都是在不斷地更新和擴(kuò)展中發(fā)展起來的,Python也不例外。說實(shí)話,Python的一些語法擴(kuò)展,還是非常精妙和必要的,比如Py3.8引入的海象運(yùn)算符(:=),就是一個典型的例子。引入海象運(yùn)算符之前,若要將一個不足16位長的字符串s用#補(bǔ)足16位(若大于或等于16位則原樣輸出),一般寫成下面這樣。
          >>>?s?=?'Hello?Wold'
          >>>?s?+?'#'*(16-len(s))?if?len(s)?16
          ?else?s
          'Hello?Wold######'
          這個代碼中兩次計(jì)算字符串s的長度,顯然,這不是一個高效的代碼。但是如果使用一個臨時變量保存字符串s的長度,又不夠優(yōu)雅。海象運(yùn)算符正是為了解決這一類問題而誕生的。
          >>>?s?=?'Hello?Wold'
          >>>?s?+?'#'*(16-c)?if?(c:=len(s))?16
          ?else?s
          'Hello?Wold######'
          可惜,不是所有的擴(kuò)展都像海象運(yùn)算符這樣美妙,甚至其中的很大一部分?jǐn)U展并未展現(xiàn)出足夠的必要性和不可替代性,只是給程序員帶來更多使用上的困惑。比如,Py3.9新增的字典合并(|)和更新(|=)運(yùn)算符,當(dāng)屬此列。
          >>>?a?=?{'x':1,?'y':2}
          >>>?b?=?{'y':3,?'z':4}
          >>>?a?|?b?#?返回一個新的字典
          {'x':?1,?'y':?3,?'z':?4}
          >>>?a?|=?b?#?將b合并到a中
          >>>?a
          {'x':?1,?'y':?3,?'z':?4}
          嚴(yán)重懷疑Python團(tuán)隊(duì)的人忘記了字典還有個update()方法可以實(shí)現(xiàn)這兩個新的運(yùn)算符的功能。
          >>>?a?=?{'x':1,?'y':2}
          >>>?b?=?{'y':3,?'z':4}
          >>>?a.update(b)
          >>>?a
          {'x':?1,?'y':?3,?'z':?4}
          也許有人會說,就算字典更新運(yùn)算符(|=)和update()功能完全重疊,可字典合并運(yùn)算符(|)返回的是一個新字典,而update()改變了原先的字典。對于持有這種想法的人,我只能悄悄提醒一下,Python對此早有解決方案。
          >>>?{**a,?**b}
          {'x':?1,?'y':?3,?'z':?4}


          5. 越俎代庖的字符串方法

          大量的內(nèi)置函數(shù)或方法,固然可以為程序員帶來更多的便利,但也會使系統(tǒng)臃腫,同時增加了入門難度,使學(xué)習(xí)曲線變得陡峭。如何平衡這個尺度,是一個見仁見智的問題。在我看來,不斷增加函數(shù)和方法,不但違背了Python的初衷,破壞了API的穩(wěn)定性,也讓程序員失去了選擇和樂趣。比如,Py3.9為str對象新增了removeprefix()和removesuffix()兩個方法,分別用于刪除字符串前綴和后綴。
          >>>?s?=?'[主播]上港獲得前場任意球(1:1)'
          >>>?s.removeprefix('[主播]')
          '上港獲得前場任意球(1:1)'
          >>>?s.removesuffix('(1:1)')
          '[主播]上港獲得前場任意球'
          類似的應(yīng)用需求有很多,如果都要加入到str對象的方法庫中,str對象將會變得無比龐大。此類函數(shù)的編寫,分明應(yīng)該交由程序員去做,Python語言項(xiàng)目組只需要關(guān)注基礎(chǔ)的和核心的方法即可。實(shí)際上,這兩個方法實(shí)現(xiàn)起來,也不過是一行代碼而已。
          >>>?s?=?'[主播]上港獲得前場任意球(1:1)'
          >>>?s?if?s.find('[主播]')?0
          ?else?s[len('[主播]'):]
          '上港獲得前場任意球(1:1)'
          >>>?s?if?(n:=s.rfind('(1:1)'))?0?else?s[:n]
          '[主播]上港獲得前場任意球'


          6. 啼笑皆非的字符串前綴

          Py2時代,u是最常見的字符串前綴,Py3時代,u前綴銷聲匿跡,b成為了最常見的字符串前綴。無論是Py2還是Py3,原生字符串前綴r都是Python程序員眼中的熟客。從Py3.6開始,突然又冒出來一個新的字符串前綴。
          >>>?score?=?'1:1'
          >>>?f'當(dāng)前比分{score}'
          '當(dāng)前比分1:1'
          以前的前綴,僅僅是一個標(biāo)識,現(xiàn)在的f前綴則變成了一種運(yùn)算符,感覺美妙的理性世界瞬間崩塌了!然而,這只是一個開始,更糟糕的事情發(fā)生在Py3.8版本上,他們居然又為這個f前綴增加了等號(=)的支持。
          >>>?語文=95
          >>>?數(shù)學(xué)=100
          >>>?f'{語文=},{數(shù)學(xué)=}'
          '語文=95,數(shù)學(xué)=100'
          MyGod,這哪兒是代碼,簡直是神符!說實(shí)話,格式化字符串時,除了C語言風(fēng)格的%外,我連format()函數(shù)都沒用過,現(xiàn)在卻有可能要面對同事寫出來的包含加強(qiáng)版f前綴的代碼。傷心的我,只能一笑了之。

          7. 不講邏輯的字典順序

          Py3.6發(fā)布的時候,就有人到處宣傳說,字典有序了。起初我以為那不過自媒體出于獵奇的目的,隨便說說,吸引眼球的。在邏輯上,字典是數(shù)據(jù)的無序集合,僅依賴于鍵檢索,如果字典有序,那就不是字典了。沒想到,Py3.7居然真的將“字典保持插入順序”作為新增特性正式對外公布了。幸好,官方說的是“字典保持插入順序”,而不是“字典有序”,總算為邏輯保留了最后的底褲。
          我說字典無序,不是指字典在物理實(shí)體上實(shí)現(xiàn)的時候真的無序,而是指它的順序?qū)τ脩舳詻]有明確的界定,不能作為數(shù)據(jù)的特性使用。也許Py3.7使用了新的機(jī)制可以更高效地存儲和檢索字典數(shù)據(jù),但這并不是程序員所關(guān)注的。新的機(jī)制帶來的字典順序穩(wěn)定,并不能成為我們可以信賴和使用的字典屬性。

          8. 惟恐天下不亂的函數(shù)參數(shù)限定符

          說到函數(shù)的定義和傳參,恐怕沒有比Python更靈活的語言了。方便的同時,位置參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)等幾種參數(shù)類型和使用順序,也給程序員帶來了很多使用上的困惑。然而,Py3.8堅(jiān)定地認(rèn)為,函數(shù)參數(shù)的使用還不夠混亂,還需要再刺激一下,以期達(dá)到從大亂到大治的目的。于是,函數(shù)參數(shù)限定符登場了——為了增強(qiáng)效果,Python官方選擇斜杠(/)作為這個限定符的表現(xiàn)形式。
          讓我們一起來嘗試著讀一讀下面這段代碼。
          >>>?def?func(a,?b,?/,?c,?d,?*,?e,?f):
          ????????print('OK')

          >>>?func(1,2,3,4,e=5,f=6)
          OK
          >>>?func(1,2,3,d=4,e=5,f=6)
          OK
          這里,a, b是位置參數(shù),e, f是關(guān)鍵字參數(shù),c, d既可以是位置參數(shù),也可以是關(guān)鍵字參數(shù)。好了,關(guān)于函數(shù)參數(shù)限定符就說這么多吧,反正也用不著——除非你是在用Python函數(shù)完全模擬C代碼編寫的函數(shù)。

          9. 毫無優(yōu)雅感的泛型函數(shù)

          說到泛型,Python程序員通常會有兩種表情:一種是驚訝:“Python有泛型嗎?”;另一種是哂笑:“Python有型嗎?”且不討論P(yáng)ython是否“有型”,作為動態(tài)語言,泛型難道不是與生俱來的嗎?也許Python團(tuán)隊(duì)不這么認(rèn)為,或者他們認(rèn)為Python程序員不這么認(rèn)為。為了配得上編程語言排行榜上大佬的位次,從Py3.4開始,Python團(tuán)隊(duì)就為Python定制了一個泛型函數(shù)裝飾器。無奈這個機(jī)制實(shí)在太過牽強(qiáng),用它寫出來得代碼丑得一批,估計(jì)沒幾個人會用它。
          >>>?from?functools?import?singledispatch
          >>>?@singledispatch
          def?say_hello(x):
          ????print('抱歉,我不認(rèn)識你')

          >>>?@say_hello.register(int)
          def?_(x):
          ????print('你好,整數(shù)')

          >>>?@say_hello.register(str)
          def?_(x):
          ????print('你好,字符串')

          >>>?say_hello(5)
          你好,整數(shù)
          >>>?say_hello('abc')
          你好,字符串
          >>>?say_hello([1,2,3])
          抱歉,我不認(rèn)識你
          上面這一大堆的代碼,只是定義了一個函數(shù)say_hello(),可以根據(jù)傳入?yún)?shù)的類型不同而做出不同反應(yīng)。如果不使用泛型裝飾器,實(shí)現(xiàn)起來更加簡單且易讀。
          >>>?def?say_hello(x):
          ????????if?isinstance(x,?int):
          ????????????print('你好,整數(shù)')
          ????????elif?isinstance(x,?str):
          ????????????print('你好,字符串')
          ????????else:
          ????????????print('抱歉,我不認(rèn)識你')

          >>>?say_hello(5)
          你好,整數(shù)
          >>>?say_hello('abc')
          你好,字符串
          >>>?say_hello([1,2,3])
          抱歉,我不認(rèn)識你


          10. 前后打臉的亡羊補(bǔ)牢

          當(dāng)我第一次讀到typing.List和typing.Dict的時候,有那么一小會兒,感覺像是在讀java或者是C++的代碼。為什么不是熟悉的list和dict呢?僅僅是為了類型提示(type hints) ,為了讓集成開發(fā)工具讀懂代碼,生生搞出了比list和dict還復(fù)雜的概念。最終的結(jié)果是,IDE讀懂了代碼,程序員卻看不明白了。
          好在Py3.9對類型提示做了改進(jìn),為內(nèi)置的以及標(biāo)準(zhǔn)庫中的集合類型提供了用于類型提示中的泛型的支持,解決了一直以來Python代碼中會出現(xiàn)兩種list(list 和 typing.List)類型的尷尬情況,也算是亡羊補(bǔ)牢吧。

          羅里吧嗦寫了這么多,希望不會讓Python程序員心生沮喪。事實(shí)上,不管我或者我們?nèi)绾瓮虏郏琍ython依然是一門偉大的編程語言。本文僅代表個人觀點(diǎn)!

          瀏覽 41
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  高清无码视频在线观看 | 欧美日韩在线看豆花 | 久久这里 | 国产精品激情小视频 | 秋霞 久久 日本 |