作者Muscovy (三分熟的闹钟)
看板Soft_Job
标题Re: [讨论] Python 3.10将加入Switch-Case语句
时间Sat Mar 27 16:09:33 2021
※ 引述《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://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1616832576.A.DCB.html
1F:→ bazoo: 请问这是使用 numpy 吗? 03/27 16:19
2F:→ bazoo: for 回圈的范例那边 03/27 16:19
3F:→ Muscovy: 是. python 内建的也有类似的写法, 但 numpy 比较简洁. 03/27 16:21
4F:推 neo5277: 好像是满好玩的 关心值 不知道会不会比较有效果 03/27 18:24
5F:→ Murasaki0110: 变成5次for好在哪里 03/27 18:33
6F:→ alihue: 第二种其实 eig 会被 scan 五次?效能不是比较差吗 03/27 18:51
7F:→ handsomeLin: 我是python progammer但是我用if else 不会用5n回圈 03/27 18:54
8F:推 jack82822005: 看起来似乎比较好懂,但效能比较差的样子 03/27 19:11
9F:推 alihue: 其实第二个可读性没比第一个好 後人还会觉得干嘛不用一个 03/27 19:29
10F:→ alihue: 回圈 03/27 19:29
11F:→ alihue: 你若要raise ex,第二种更难读出何时会 raise ex 03/27 19:32
12F:→ alihue: 然後如果你 pass 里面资料是不能被重复处理的,在第二种 03/27 19:39
13F:→ alihue: case 若条件有 overlap 会出 bug 03/27 19:39
14F:推 Celinealone: 不太懂为什麽第二个会比较好维护? Python也可以用第 03/27 20:31
15F:→ Celinealone: 一种写法不是吗? 03/27 20:31
16F:→ WunoW: 明明就if-else比较好维护吧... 03/27 20:35
17F:推 drajan: “pythonic” 03/27 20:40
18F:推 mirror0227: 我也选 if else 03/27 20:46
19F:→ geniusturtle: 觉得第二种不好读 03/27 20:48
20F:推 noahleft: 第二种以维护角度比较容易, 第一种当条件混入各种可能後 03/27 21:04
21F:→ noahleft: 会很难知道甚麽时候会跑到哪个条件 03/27 21:05
22F:→ noahleft: 只要考虑到有情形是多个条件都能成立时,第一种写法就是 03/27 21:06
23F:→ noahleft: 看执行顺序,而第二种写法会变成喂进来的资料都是符合条 03/27 21:07
24F:→ noahleft: 见的 03/27 21:07
25F:→ WunoW: 多条件你就用多个if就好不用else了 = = 03/27 21:10
26F:→ noahleft: 补充一下 多条件指可能你的condition并非完全互斥 03/27 21:22
27F:→ hsnuyi: 又是一个不考虑CPU如何branch的人 03/27 21:51
28F:→ WunoW: NO 你先if排除不符合的条件更直观也有更好的效能 03/27 21:53
29F:→ WunoW: 我知道你是想遵循单一职责原则,但这不是定律 03/27 21:58
30F:→ WunoW: 一个回圈做多个判断没有不行 你判断式提取为函式就好 03/27 22:00
31F:推 alihue: 楼上说到一个重点...if的位置在某些情况可以大幅改善效能 03/27 22:02
32F:→ WunoW: 你去看pandas的源码吧 一个for loop里面包山包海的code一堆 03/27 22:03
33F:→ alihue: 例如在回圈的一开始就筛掉大部分 case 并 continue 03/27 22:04
34F:推 MoonCode: 先写的简单好懂比效能重要 推推 03/27 22:09
35F:推 jack0204: 楼上说的这叫early return,写可读性高的程式常用到 03/27 22:22
37F:→ shooter555: for in 後面的条件不会先被展开吗 这样不是比较慢? 03/29 12:38
38F:→ shooter555: 然後第二种写写一大长串不是很难看吗 第一种虽然一堆 03/29 12:41
39F:→ shooter555: 一次性的func 但拿来命名可以清楚看出他是要干麽的 03/29 12:41
40F:推 s0914714: 以这个例子而言 的确1的写法不会比较差 就是分区而已 03/30 17:14
41F:→ s0914714: 但复杂情况2的维护性会高不少 03/30 17:14
42F:→ red0210: in 後面计算量通常不大(跟里面那堆比),拿去profiling 04/04 15:42
43F:→ red0210: 就知道了 04/04 15:42