久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

危險(xiǎn)的轉(zhuǎn)變:Python正在從簡明轉(zhuǎn)向臃腫,從實(shí)用轉(zhuǎn)向媚俗

 天選小丑 2020-11-04

作者 | 天元浪子

頭圖 | CSDN  

出品 | CSDN 博客

國慶長假期間,,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正在背離我最初所期望的簡潔和易用,變得越來越臃腫和不可控制,?!?/p>

曾經(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),,排名不分先后。

媚俗的靜態(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ā)工具(IDE),同時滿足不明就里的程序員的成就感和虛榮心罷了,。

畫蛇添足的變量類型聲明

當(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ù),。差評!

雞肋般的函數(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 Uniondef 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)證(除非使用類型檢查工具),更不會有長度檢查,。如果想要這些功能,,一切還得靠自己。

不加限制的擴(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}

越俎代庖的字符串方法

大量的內(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]'[主播]上港獲得前場任意球'

啼笑皆非的字符串前綴

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前綴的代碼。傷心的我,,只能一笑了之,。

不講邏輯的字典順序

Py3.6發(fā)布的時候,就有人到處宣傳說,,字典有序了,。起初我以為那不過自媒體出于獵奇的目的,隨便說說,,吸引眼球的,。在邏輯上,字典是數(shù)據(jù)的無序集合,,僅依賴于鍵檢索,,如果字典有序,那就不是字典了,。沒想到,,Py3.7居然真的將“字典保持插入順序”作為新增特性正式對外公布了。幸好,,官方說的是“字典保持插入順序”,,而不是“字典有序”,總算為邏輯保留了最后的底褲,。

我說字典無序,,不是指字典在物理實(shí)體上實(shí)現(xiàn)的時候真的無序,而是指它的順序?qū)τ脩舳詻]有明確的界定,,不能作為數(shù)據(jù)的特性使用,。也許Py3.7使用了新的機(jī)制可以更高效地存儲和檢索字典數(shù)據(jù),但這并不是程序員所關(guān)注的,。新的機(jī)制帶來的字典順序穩(wěn)定,,并不能成為我們可以信賴和使用的字典屬性。

惟恐天下不亂的函數(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ù)。

毫無優(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>>> @singledispatchdef 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)識你

前后打臉的亡羊補(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ǔ)牢吧,。

作者聲明:本文觀點(diǎn)僅是我作為一個原教旨主義者的個人觀點(diǎn),,稍微摻雜了一點(diǎn)調(diào)侃,歡迎各位發(fā)表高見,。

原文地址:https://blog.csdn.net/xufive/article/details/109253333?spm=1000.2115.3001.4373

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多