奇技淫巧不可取,切記切記

文 |?軒轅御龍
來(lái)源:Python 技術(shù)「ID: pythonall」

之前我們介紹過(guò)Python有一個(gè)模塊可以用來(lái)檢查代碼風(fēng)格,并且u1s1,檢查得還挺嚴(yán)的,搞得阿醬還挺怕怕的
就像讀書時(shí)候有一個(gè)嚴(yán)厲的老大哥、啊不對(duì),老師,一直始終盯著你,一旦犯錯(cuò)就會(huì)對(duì)你提出嚴(yán)厲的批評(píng),羞得你無(wú)地自容。

上次就是這個(gè)老師,又把阿醬給訓(xùn)了一頓。不過(guò)講心里話,老師訓(xùn)得還是有道理的,阿醬雖然口頭上不爽嘟囔兩句,但物理上也還是從善如流的——這肯定不是怕了老師手上的戒尺。
下面我就給大家好好兒講講我是怎么被訓(xùn)的——
問(wèn)題呈現(xiàn)
作為Python的語(yǔ)法糖之一,想必大家對(duì)于列表生成式都已經(jīng)熟悉得不能再熟悉了,甚至現(xiàn)在立馬走出門去,不懂列表生成式都不敢理直氣壯地說(shuō)自己是個(gè)Pythonista——到了這種程度。
另外附贈(zèng)一篇《Pythoneer和Pythonista的區(qū)別》以饗大家,不另行收費(fèi)。
——啊!好像我們本來(lái)也不收費(fèi)?
但是上次坑了阿醬的恰好就是這個(gè)列表生成式,這里也跟大家share一下阿醬的辛酸故事。(類似的話我前兩句是不是才說(shuō)過(guò)來(lái)著
話說(shuō)那是一個(gè)月黑風(fēng)高的夜晚(程序猿加班很正常對(duì)伐?所以這個(gè)描述很合理且應(yīng)景),阿醬當(dāng)時(shí)辛辛苦苦耕耘,碼出了好長(zhǎng)一段代碼,然后喜滋滋地例行pylint掃了一下……

啊咧?什么鬼?
R1721:?Unnecessary?use?of?a?comprehension
不需要用列表生成式?
寫的啥?
l?=?[n?for?n?in?range(10)]
有毛病嗎?這有毛病嗎?這***有啥毛病啊?你倒是說(shuō)啊?我這代碼有什么問(wèn)題?咋就不該用列表生成式了?那你讓我用啥?用愛嗎?

冤有頭債有主
好了到這里卡住了,接下來(lái)有請(qǐng)我們永遠(yuǎn)滴神——Google老大爺蹣跚登場(chǎng)
輸入,搜索,到手!

讓我們點(diǎn)開看起來(lái)更正規(guī)的第二個(gè)鏈接——至于我為什么說(shuō)第二個(gè)更正規(guī)呢?阿醬當(dāng)然不會(huì)告訴你我已經(jīng)都點(diǎn)開看過(guò)了
翻譯一下,第二個(gè)鏈接標(biāo)題“Enhancement: Add a [unnecessary-comprehension]-checker”,大概是“改進(jìn)點(diǎn):添加[unnecessary-comprehension]檢查器”這么個(gè)意思——
什么什么?你給我等下。
感情剛剛困擾我的那個(gè)規(guī)范問(wèn)題還是打你這兒出來(lái)的啊,冤有頭債有主,別怪我不客……咳,讀書人的事,終歸還是講點(diǎn)道理的,咱們還是先把這鏈接的內(nèi)容看完,再不客氣也不遲。
這位老哥說(shuō)了啥來(lái)著?
...
we could implement a checker that detects list/dict/set-comprehensions that can be replaced by the corresponding list/dict/set-constructors, which is faster and more readable. For example:
list(iterable)instead of[x for x in iterable]dict(some_dict)instead of{k: v for k, v in some_dict}set(iterable)instead of{e for e in iterable}Although these cases seem trivial/obvious, I think having such a checker would help in cases where longer/more complex variable-names are used.
...
老哥說(shuō),他要實(shí)現(xiàn)這么一個(gè)檢查器,檢查出那些可以被list/set/dict構(gòu)造器替換的list/set/dict生成式,使代碼性能更佳、可讀性更好。具體來(lái)說(shuō)有這么些blabla的示例。
再仔細(xì)一看,嗨,真有道理
你看看這個(gè)列表生成式,[x for x in iterable],這不是脫了屁股放……啊錯(cuò)了,脫了褲子放屁嗎?一個(gè)個(gè)迭代出來(lái)可迭代對(duì)象中的元素,然后原封不動(dòng)地組裝成一個(gè)列表;這種弱智活,直接交給內(nèi)置的list不香嗎?還會(huì)有傻*蠢到用列表生成式?哈哈哈哈哈哈,?——
淦!我TM就是那個(gè)傻*?
奇技淫巧要慎用
u1s1,在此之前,我從來(lái)沒(méi)有想過(guò),一個(gè)簡(jiǎn)單的列表生成式還有這么多的講究,壓根兒就沒(méi)有考慮過(guò)怎么樣才能有效地使用Python的語(yǔ)法糖。
然而實(shí)際上,事實(shí)證明語(yǔ)法糖畢竟是語(yǔ)法糖,有其適用的場(chǎng)景,當(dāng)然也有其不適用的場(chǎng)景。
沒(méi)有什么東西是萬(wàn)金油銀彈(這個(gè)修改是阿醬為了顯得與國(guó)際接軌),只有用在了對(duì)的地方,它才能被稱之為“語(yǔ)法糖”;否則更像是“語(yǔ)法毒藥”,污染好大一片數(shù)字江山。
包括阿醬在內(nèi)的不少同學(xué),可能學(xué)了一陣兒Python,就沉浸于其中的各種奇技淫巧,每次遇到任何場(chǎng)景,都是不管三七二十一,直接套上一個(gè)trick。
你以為你是四兩撥千斤,其實(shí)不過(guò)是大力出奇跡。
pylint增加的這個(gè)檢查器能夠檢查的項(xiàng)不止于列表生成式這么一小塊門類,繼續(xù)閱讀之前那個(gè)鏈接我們可以發(fā)現(xiàn)一套很有意義的范例,其中注釋為[unnecessary-comprehension]的代碼行,都是相關(guān)生成式的“壞的實(shí)踐”,值得我們引以為鑒。
相關(guān)內(nèi)容作為附錄附在本文之后。
總結(jié)
本文我們?cè)俅危ò⑨u要哭了)從阿醬遇到的實(shí)際問(wèn)題說(shuō)開去,警醒了一些有點(diǎn)飄的同學(xué):我們一定要腳踏實(shí)地,仰望星空;艱苦奮斗,持續(xù)搬磚。
奇技淫巧可以用,但是一定要分清場(chǎng)景。
參考資料
Enhancement: Add a [unnecessary-comprehension]-checker #2905
附錄
#?For?name-reference?see?https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries
#?List?comprehensions
[x?for?x?in?iterable]??#?[unnecessary-comprehension]
[y?for?x?in?iterable]??#?expression?!=?target_list
[x?for?x,y,z?in?iterable]??#?expression?!=?target_list
[(x,y,z)?for?x,y,z?in?iterable]??#?[unnecessary-comprehension]
[(x,y,z)?for?(x,y,z)?in?iterable]??#?[unnecessary-comprehension]
[x?for?x,?*y?in?iterable]??#?expression?!=?target_list
[x?for?x?in?iterable?if?condition]??#?exclude?comp_if
[y?for?x?in?iterable?for?y?in?x]??#?exclude?nested?comprehensions
#?Set?comprehensions
{x?for?x?in?iterable}??#?[unnecessary-comprehension]
{y?for?x?in?iterable}??#?expression?!=?target_list
{x?for?x,y,z?in?iterable}??#?expression?!=?target_list
{(x,y,z)?for?x,y,z?in?iterable}??#?[unnecessary-comprehension]
{(x,y,z)?for?(x,?y,?z)?in?iterable}??#?[unnecessary-comprehension]
{x?for?x,?*y?in?iterable}??#?expression?!=?target_list
{x?for?x?in?iterable?if?condition}??#?exclude?comp_if
{y?for?x?in?iterable?for?y?in?x}??#?exclude?nested?comprehensions
#?Dictionary?comprehensions
{k:?v?for?k,?v?in?iterable}??#?[unnecessary-comprehension]
{v:?k?for?k,?v?in?iterable}??#?key?value?wrong?order
{k:?v?for?(k,?v)?in?iterable}??#?[unnecessary-comprehension]
{x:?y?for?x,y,z?in?iterable}??#?expression?!=?target_list
{x[0]:?x[1]?for?*x?in?iterable}??#?[unnecessary-comprehension]
{x:?y?for?x,?y?in?iterable?if?condition}??#?exclude?comp_if
{y:?z?for?x?in?iterable?for?y,?z?in?x}??#?exclude?nested?comprehensions
PS:公號(hào)內(nèi)回復(fù)「Python」即可進(jìn)入Python 新手學(xué)習(xí)交流群,一起 100 天計(jì)劃!
老規(guī)矩,兄弟們還記得么,右下角的 “在看” 點(diǎn)一下,如果感覺文章內(nèi)容不錯(cuò)的話,記得分享朋友圈讓更多的人知道!


【代碼獲取方式】
