Re: [討論] Python 3.10將加入Switch-Case語句

看板Soft_Job作者 (三分熟的鬧鐘)時間3年前 (2021/03/27 16:09), 編輯推噓12(12029)
留言41則, 19人參與, 3年前最新討論串2/6 (看更多)
※ 引述《ohmylove347 (米特巴爾)》之銘言: : https://reurl.cc/8yzA24 : 上面說2006年 PEP 3103就建議實施switch-case語句。 : 但是,在PyCon 2007上的一項民意調查未獲得對該功能的支持後, : Python開發人員將其刪除。 : : 沒有使用Python不知道生態系如何 : Google App上看到的文章 : 不知道各位大大對Switch加入有什麼看法 : : 推 Muscovy: for/while 比 if-else 常出現無誤, 大概 10:1 的比例. XD : 推 TAMSHUI: 不知M大能否舉例完全不用if-else呢?Google了一下還是沒 : → TAMSHUI: 什麼想法@@ : 推 Muscovy: 不會到完全不寫 if 的程度啦,等一下我來整理一篇 我的工作環境很雜, 從 matlab 到 C 與他的親朋好友(java 也算. :D) 反正猴子用 C, 有錢的猴子用 matlab, 沒錢的猴子像我就用 python. 但是大概都會雙棲... 我來舉個例子... 譬如你有一組數字, 數量不多不少, 大約 10,000 個左右. 然後要處理它, 先叫他 eigen_spectrum, 或者簡稱 eig 好了. 當 eigen_spectrum >= 100,000,000 的時候要做一堆事. 介於 [10, 100,000,000) 的時候又一堆事. 介於 (0, 10) 的時候又一堆. 剛好等於 0 的時候需要處理特殊事件. 然後小於 0 的話要檢查有沒有奇怪的現象, 標注一些警示. 這些事情的執行細節通通都不太一樣, 然後要怎麼做? 用 C 的話, 大概 if-else/if-else/if-...-else 之外就沒招了. 所以 python by C programmer 會變這樣: for s in eigen_spectrum: if s >= 1e8: pass # 這裡寫一大坨, 頂多寫個函數處理. elif s >= 10 and s < 1e8: pass # 這裡再一坨, 或者寫個跟上面不一樣函數. elif s > 0 and s < 10: pass # 再一坨, 或者再一個跟上面都不同的函數. elif s == 0: pass # 嗯, 你知道的, 繼續. elif s < 0: pass # 嗯......寫就對了. else: raise ValueError("Should not happen.") 最後你會得到一堆只用一次的函數, 或者一大串超長程式碼. 但是 python programmer 呢, 會這樣寫: for s in eig[eig > 1e8]: pass # 寫寫寫, 也是一大坨. for s in eig[np.logical_and(eig > 10, eig < 1e8)]: pass # 繼續寫寫寫, 也是一坨. for s in eig[np.logical_and(eig > 0, eig < 10)]: pass # 再寫, 繼續就對了. if np.any(eig == 0): pass # 驚醒! 想一下遇上 0 的時候要做什麼. for s in eig[eig < 0]: pass # 再寫再寫, 反正就是接龍. 很有趣的結構吧? 你還是會變出一段超長程式碼. 再加上明明一個迴圈可以搞定的事, 硬要拆成四個. 還補了一個莫名其妙, 不太對稱的 if. 但事實上這種寫法比較好維護, 因為這個結構更近似數學的模型. 可以往前翻到我上面的文字敘述, 比看看兩種寫法就知道了. 這個數學模型很簡單, 然而不同的寫法就已經有風格上的區分. 稍微複雜一點的數學模型, 用 if-elif-else 就更難重建. 譬如這個 eigen_spectrum 會有一組伴隨的 eigen_states 要處理. 用 if-else 硬爬會爬出一堆腦袋打結的程式碼, 因為很不像數學. 然後結構裡面的 if 其實是用來做 s == 0, exception handle. 而且這也是我最常遭遇的情境: 用 if + raise 來表示異常狀況. 其他時候, 我一下子想不太到寫 if statement 的情況. 因為翻到的程式碼幾乎都是: if np.count_nonzero(np.abs(s) < 1e-8) > 2: raise ValueError('Too many singularities.') 這一類的東西, 它就是有個 raise. : → as30385438: 不用if就是用loop、dict的key放condition或一些DP手法 : → as30385438: 寫python的常常追求所謂的pythonic,不過我自己是覺得 : → as30385438: simple is best,最直覺的寫法通常就是最好的 從 stackoverflow 容易學到的毛病就是把 one-liner 當成 pythonian. 養成這種習慣的程式員有夠難矯正. -- 新詩練習:新鮮。踩破初春裡的狗大便;不經意的滄桑,滿溢著嫩黃的喜悅。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.248.47.50 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1616832576.A.DCB.html

03/27 16:19, 3年前 , 1F
請問這是使用 numpy 嗎?
03/27 16:19, 1F

03/27 16:19, 3年前 , 2F
for 迴圈的範例那邊
03/27 16:19, 2F

03/27 16:21, 3年前 , 3F
是. python 內建的也有類似的寫法, 但 numpy 比較簡潔.
03/27 16:21, 3F

03/27 18:24, 3年前 , 4F
好像是滿好玩的 關心值 不知道會不會比較有效果
03/27 18:24, 4F

03/27 18:33, 3年前 , 5F
變成5次for好在哪裡
03/27 18:33, 5F

03/27 18:51, 3年前 , 6F
第二種其實 eig 會被 scan 五次?效能不是比較差嗎
03/27 18:51, 6F

03/27 18:54, 3年前 , 7F
我是python progammer但是我用if else 不會用5n迴圈
03/27 18:54, 7F

03/27 19:11, 3年前 , 8F
看起來似乎比較好懂,但效能比較差的樣子
03/27 19:11, 8F

03/27 19:29, 3年前 , 9F
其實第二個可讀性沒比第一個好 後人還會覺得幹嘛不用一個
03/27 19:29, 9F

03/27 19:29, 3年前 , 10F
迴圈
03/27 19:29, 10F

03/27 19:32, 3年前 , 11F
你若要raise ex,第二種更難讀出何時會 raise ex
03/27 19:32, 11F

03/27 19:39, 3年前 , 12F
然後如果你 pass 裡面資料是不能被重複處理的,在第二種
03/27 19:39, 12F

03/27 19:39, 3年前 , 13F
case 若條件有 overlap 會出 bug
03/27 19:39, 13F

03/27 20:31, 3年前 , 14F
不太懂為什麼第二個會比較好維護? Python也可以用第
03/27 20:31, 14F

03/27 20:31, 3年前 , 15F
一種寫法不是嗎?
03/27 20:31, 15F

03/27 20:35, 3年前 , 16F
明明就if-else比較好維護吧...
03/27 20:35, 16F

03/27 20:40, 3年前 , 17F
“pythonic”
03/27 20:40, 17F

03/27 20:46, 3年前 , 18F
我也選 if else
03/27 20:46, 18F

03/27 20:48, 3年前 , 19F
覺得第二種不好讀
03/27 20:48, 19F

03/27 21:04, 3年前 , 20F
第二種以維護角度比較容易, 第一種當條件混入各種可能後
03/27 21:04, 20F

03/27 21:05, 3年前 , 21F
會很難知道甚麼時候會跑到哪個條件
03/27 21:05, 21F

03/27 21:06, 3年前 , 22F
只要考慮到有情形是多個條件都能成立時,第一種寫法就是
03/27 21:06, 22F

03/27 21:07, 3年前 , 23F
看執行順序,而第二種寫法會變成餵進來的資料都是符合條
03/27 21:07, 23F

03/27 21:07, 3年前 , 24F
見的
03/27 21:07, 24F

03/27 21:10, 3年前 , 25F
多條件你就用多個if就好不用else了 = =
03/27 21:10, 25F

03/27 21:22, 3年前 , 26F
補充一下 多條件指可能你的condition並非完全互斥
03/27 21:22, 26F

03/27 21:51, 3年前 , 27F
又是一個不考慮CPU如何branch的人
03/27 21:51, 27F

03/27 21:53, 3年前 , 28F
NO 你先if排除不符合的條件更直觀也有更好的效能
03/27 21:53, 28F

03/27 21:58, 3年前 , 29F
我知道你是想遵循單一職責原則,但這不是定律
03/27 21:58, 29F

03/27 22:00, 3年前 , 30F
一個迴圈做多個判斷沒有不行 你判斷式提取為函式就好
03/27 22:00, 30F

03/27 22:02, 3年前 , 31F
樓上說到一個重點...if的位置在某些情況可以大幅改善效能
03/27 22:02, 31F

03/27 22:03, 3年前 , 32F
你去看pandas的源碼吧 一個for loop裡面包山包海的code一堆
03/27 22:03, 32F

03/27 22:04, 3年前 , 33F
例如在迴圈的一開始就篩掉大部分 case 並 continue
03/27 22:04, 33F

03/27 22:09, 3年前 , 34F
先寫的簡單好懂比效能重要 推推
03/27 22:09, 34F

03/27 22:22, 3年前 , 35F
樓上說的這叫early return,寫可讀性高的程式常用到
03/27 22:22, 35F

03/27 23:16, 3年前 , 36F

03/29 12:38, 3年前 , 37F
for in 後面的條件不會先被展開嗎 這樣不是比較慢?
03/29 12:38, 37F

03/29 12:41, 3年前 , 38F
然後第二種寫寫一大長串不是很難看嗎 第一種雖然一堆
03/29 12:41, 38F

03/29 12:41, 3年前 , 39F
一次性的func 但拿來命名可以清楚看出他是要幹麼的
03/29 12:41, 39F

03/30 17:14, 3年前 , 40F
以這個例子而言 的確1的寫法不會比較差 就是分區而已
03/30 17:14, 40F

03/30 17:14, 3年前 , 41F
但複雜情況2的維護性會高不少
03/30 17:14, 41F
文章代碼(AID): #1WNkX0tB (Soft_Job)
討論串 (同標題文章)
文章代碼(AID): #1WNkX0tB (Soft_Job)