看到不同的同事代码,表达同一个意思,主要 if
部分以下哪种写法比较好些:)
def xxxx(ph, sin_id):
"""
"""
with OracleConnect(xxxx) as db_oracle:
sql = u"xxxxx"
has_data, sql_data = db_oracle.get_one(sql)
# 第一种写法
if has_data:
calculate_func = "rollback"
task_id = sql_data.get("task_id", "")
else:
calculate_func = "calculate"
task_id = sin_id
return task_id, calculate_func
def xxxx(ph, sin_id):
"""
"""
with OracleConnect(xxxx) as db_oracle:
sql = u"xxxxx"
has_data, sql_data = db_oracle.get_one(sql)
# 第二种写法
calculate_func = "rollback" if has_data else "calculate"
task_id = sql_data.get("task_id", "") if has_data else sin_id
return task_id, calculate_func
第一种写法,比较直接,清晰明了,但有同事说不够 pythonic
。
第二种写法比较 pythonic
,但是类似写法,对于刚接手别人代码的同事,就要稍微绕一下才能读懂。
由此拓展,想到在写业务逻辑中,经常会有 if
语句的判断,请问大家是怎么选择代码风格的:)
1
qwertyzzz 2018-12-10 22:28:29 +08:00
虽然我不会 python 但是我喜欢看第一种
|
2
dd0754 2018-12-10 22:33:55 +08:00 via iPhone
分情况,这种用第一种
|
3
arthasgxy 2018-12-10 22:38:04 +08:00 34
“但有同事说不够 pythonic ”
等他被我这种暴徒打成 pythonfuck 之后,他就知道错了 |
4
SimbaPeng 2018-12-10 22:42:23 +08:00
觉得第一种清晰的人只不过是先入为主,自己熟悉的东西觉得清晰,不熟悉的东西觉得绕
|
5
monkeylyf 2018-12-10 22:42:25 +08:00 2
同意二楼。
因为这里 has_data 被两次使用来用 condition check,毫无疑问第一种好。 如果 has_data 只被用一次做 condition check, 两种感觉都可以。 readability > pythonic for the sake of being pythonic |
6
southsala 2018-12-10 22:42:34 +08:00
要降低复杂度,不要炫技
|
7
DongDongXie 2018-12-10 22:45:52 +08:00
这里第一种就可以了,只需要判断一次
|
8
daweii 2018-12-10 22:46:27 +08:00 via iPhone
第一种 可读性强
|
9
blless 2018-12-10 22:50:34 +08:00 via Android
第一种
|
10
xiangyuecn 2018-12-10 22:53:57 +08:00 1
第二种会被打,前几天我给微软 github 提交了个 pull,被他们的人喷了个体无完肤,原因就是跟第二种类似
一堆这种说格式的 |
11
freestyle 2018-12-10 22:53:59 +08:00 via iPhone
无论是从性能还是可读性还是维护性方面考虑都是第一种
|
12
niubee1 2018-12-10 22:54:31 +08:00 8
或者第三种写法
def xxxx(ph, sin_id): """ 第三种写法 """ with OracleConnect(xxxx) as db_oracle: sql = u"xxxxx" has_data, sql_data = db_oracle.get_one(sql) return ("rollback", sql_data.get("task_id", "") ) if has_data else ("calculate", sin_id) 或者 第四种写法 def xxxx(ph, sin_id): """ 第四种写法 """ with OracleConnect(xxxx) as db_oracle: sql = u"xxxxx" has_data, sql_data = db_oracle.get_one(sql) if has_data: return "rollback", sql_data.get("task_id", "") else: return "calculate", sin_id 你那种多两个中间变量出来的写法啰嗦冗长可读性差, 根据剃刀原则, 如无必要勿增实体, 那两个中间变量纯属多余, 所以不是写的方法问题, 是你本身的逻辑能力问题. 是 if else 多行好还是单行好, 其实排一下版, 都挺好的. |
13
2exploring 2018-12-10 22:55:38 +08:00
没写过 Python 的来说一句,表示能看懂,这和 C/C++中的三元操作符 ? : 不是一个理吗?我同意 2 楼和 7 楼,如果只是涉及到一个变量,那我会使用第二种。
|
14
kevin1852 2018-12-10 22:55:40 +08:00
```
def xxxx(ph, sin_id): """ """ with OracleConnect(xxxx) as db_oracle: sql = u"xxxxx" has_data, sql_data = db_oracle.get_one(sql) calculate_func = "calculate" task_id = sin_id if has_data: calculate_func = "rollback" task_id = sql_data.get("task_id", "") return task_id, calculate_func ``` 不是要这么写吗? |
15
xpresslink 2018-12-10 23:01:51 +08:00 3
楼主提的这个问题根本就没有意义,这个毫无疑问要用第一种格式,注意只是格式。两种写法的逻辑和哲学本质上是一样的,只是第二种根本就不推荐在函数和业务代码中使用,只有在配置文件中条件参数的情况使用一下。
python 是动态语言,倾向于直接 try 可能存在异常的资源,使用异常处理捕捉。 另一种是先检测可用再使用,C 之类的静态语言倾向于这个哲学。 |
16
zzzhbooo 2018-12-10 23:07:45 +08:00
自己写代码随便怎么写,写出花来都没人管,团队合作除非能提高运行效率,不然就老老实实写大部分人能看懂的代码
|
17
agdhole 2018-12-10 23:09:36 +08:00
第二种是伪三元的实现?
在最好的语言里面只需要 calculate_func = has_data ? "rollback" : "calculate"; (😀 |
18
ithou 2018-12-10 23:10:49 +08:00 via Android
看第二种要疯
|
19
ericls 2018-12-10 23:13:06 +08:00 via iPhone
第二种 因为第一种你需要保证 所有在 if 里面添加的名字 在 else 里面也要有 这就多了一个出错的机会
|
21
misaka19000 2018-12-10 23:21:21 +08:00
显然是第二种
|
22
liyoubin37 2018-12-10 23:27:08 +08:00 via Android 1
前几天看到的一种写法,比楼主的第二种简洁,但不光接触过的需要绕一下才能看懂。
return [("calculate",sin_id),("rollback",sql_data.get("task_id", ""))][has_data] |
23
VDimos 2018-12-10 23:28:15 +08:00 via Android 1
rust 里推荐第二种,我觉得 rust 的编码风格很不错
|
24
AX5N 2018-12-10 23:32:11 +08:00
只从内涵考虑的话。第二种是两次控制流分别用于求两个不同的东西。如果 calculate_func 和 task_id 的关系不大的话,应该用第二种,如果关系大的话,应该用第一种。
这里应该用第一种吧 |
25
WilliamYang 2018-12-10 23:42:48 +08:00
两个变量都是根据 has_data 而变化, 因此这里不宜用第二种, 除非只是一个变量的取值. 如果有 if has_data 下有更多的变量赋值, 并且使用了第二种写法, 可能想打人
|
26
weakish 2018-12-10 23:44:45 +08:00
像 @monkeylyf 指出的,第二种写法不能让人一眼看出来,这两个变量的取值都取决于`has_data`,所以第二种写法不好,第一种好。
如果偏爱第二种的风格,那得这样写: calculate_func, task_id = ("rollback", sql_data.get("task_id", "")) if has_data else ("calculate", sin_id) 其实我个人是喜欢第二种风格的,并不像 @xpresslink 说的“本质上是一样的”,第二种写法,可以确保你不会无意中遗漏 else 的情况——像 Haskell 和 OCaml 等一堆函数语言里,if then else 都是第二种写法。 但是 python 这个东西就和 lambda 一样,都是设计来让你写很短的东西的。设想一下,以后可能需求变动,不止一个条件判断,不止赋值两个变量,第一种写法可以很方便地加 elif,可以很方便地多加几行赋值语句。而第二种写法呢?当然,可以啦,条件判断嵌套,元组可以加元素,但是这么搞,可读性会很差。 所以鉴于 python 的设计限制,虽然我喜欢第二种写法,但我还是会用第一种写法。 |
27
j2gg0s 2018-12-10 23:46:56 +08:00
大段复杂逻辑用第一种,如果只是图例的话用第二种;
认为不太直观的,如果 Python 不是你的主要语言的,我觉得可以接受,要不然退教保平安把. 第二种类似的表达式,在大多数 py 项目里面是被普遍应用的,而且确实可以节省大量的代码 我随便帮你捞几段 https://github.com/celery/celery/blob/master/celery/events/dumper.py#L71 https://github.com/celery/celery/blob/master/celery/events/dispatcher.py#L183 https://github.com/celery/celery/blob/master/celery/events/state.py#L122 |
28
weakish 2018-12-10 23:51:03 +08:00
@liyoubin37 直觉上,has_data 的值应该是 True 和 False,而不是 0 或 1,这种写法是利用了 Python 的布尔值和整数值之间的隐式转换,我不喜欢。而且习惯上,has_data,正常的思路,是先写有数据的情况,再写没数据的情况,而这种写法还要颠倒一下,看起来很别扭。
这种写法更适合条件本来就是整数的情况(因为 python 里没有 switch ... case 语句)。 |
29
ToT 2018-12-10 23:52:11 +08:00
逻辑复杂的时候,还是第一种看起来明白阿。没必要刻意去追求行数精简。
|
31
cnt2ex 2018-12-11 00:02:30 +08:00 2
主要是作用域问题,虽然在 python 里没有问题,但其实第一种写法里那两个变量的作用域只在 if 里。
而我如果把 return 放进 if 里,会导致两个分支都有相同的代码。 所以我个人更偏向于: calculate_func, task_id = ("rollback", sql_data.get("task_id", "")) if has_data else ("calculate", sin_id) |
33
leido 2018-12-11 00:15:15 +08:00 via Android
我看你同事就是傻逼
|
34
SaltyFishMo 2018-12-11 00:35:19 +08:00 via Android
@liyoubin37 这种写法,无论 has_data 的值是什么,都会执行 sql_data.get("task_id","")方法吧,是不是在一定程度上降低了效率呢?
|
35
liprais 2018-12-11 00:42:19 +08:00
30 秒看不懂的,以后都要重写
随便了,前人挖坑后人填坑呗 |
36
cgsv 2018-12-11 00:50:50 +08:00 via iPhone 1
@SaltyFishMo 跟第一种等价,false 时不执行
|
37
Yvette 2018-12-11 01:42:25 +08:00
没有代码规范的前提下,第二种显然比较直观,也不容易出错。
|
38
menc 2018-12-11 02:26:13 +08:00
result_mapping = {
'1': ('rollback', sql_data.get("task_id", "")), '0': ('calculate', sin_id) } return result_mapping(has_data) |
40
xiaket 2018-12-11 06:02:32 +08:00
我觉得你同事只怕是对 Pythonic 有什么误解.
|
41
congeec 2018-12-11 07:38:03 +08:00
|
42
poplar50 2018-12-11 07:41:45 +08:00 via Android
这种就看条件写出来长不长了,就题中的情况,我会写第一种,方便阅读。
|
43
buy2top 2018-12-11 07:46:29 +08:00 via Android
调试时候第一种容易检查,第二种容易忘异常
|
44
FrailLove 2018-12-11 08:11:20 +08:00
写倒是无所谓 我觉得第一种修改起来更简单 支持 1
|
45
LokiSharp 2018-12-11 08:29:18 +08:00 via iPhone
第一种调试起来方便,第二种调试火葬场
|
46
httplife 2018-12-11 08:32:22 +08:00
我不懂 Python,
Python 不是崇尚 "There should be one-- and preferably only one --obvious way to do it." 根据: http://google.github.io/styleguide/pyguide.html 第一种格式相对好. |
47
woodensail 2018-12-11 08:53:43 +08:00
这还需要问吗?简单逻辑写三元,复杂逻辑写 if 是常识吧。
另外,可读性不是代码越长就越好的,片面拉长代码会导致阅读代码时联系上下逻辑困难。 |
48
woodensail 2018-12-11 09:00:05 +08:00
事实上 python 的理念也就是这样,让程序员把精力集中于业务逻辑上,而不是代码技巧上。
举例而言,python 的 with 语句可以让开发者不用操心资源的关闭,python 的 defaultdict 可以让用户不用每次取完 dict 后先判一遍非空。 理想情况下的 python 应该像自然语言一样,可以通读,一行描述一条逻辑,而不是花很多行实现一个编程技巧,以完成一个特定逻辑。 |
49
zhang2e 2018-12-11 09:27:45 +08:00
有一本书,叫做《编写可读代码的艺术》,里面讲到了关于「滥用三元运算符」这个问题。
|
50
pp3182429 2018-12-11 09:28:30 +08:00
@woodensail 支持,如果 if 判断只处理一个变量就用三元表达式更方便也不影响阅读,超过就用代码块更清晰。
|
51
Woodywuuu 2018-12-11 09:28:41 +08:00
有段时间喜欢 py 只写一行,行数越少越好,各种推导式兰比达堆在一起,代码行数贼少,感觉自己很简洁了
然后第二天想改个点就看不懂自己写的是啥了 |
52
BOYPT 2018-12-11 09:30:52 +08:00
has_data 变量控制了下面代码块的总体逻辑。第二种写法虽然局部上是 pythonic 的,但是不利于代码的阅读和理解。
如果只有一行代码受 has_data 的影响,这点还有点争议性哪个好,但是只要超过一行(形成代码块),就显然应该选择第一种。 |
53
Heyavc 2018-12-11 09:33:04 +08:00
如果项目里有其他人阅读或修改的话,还是选择第一种更好。
|
54
faimin 2018-12-11 09:39:59 +08:00 via iPhone
我选择第一种,毕竟开发不是用来炫技的,可读性是很重要的
|
55
16ByUe06GJ2y3umH 2018-12-11 09:46:14 +08:00
@j2gg0s #27 恕我直言, 你搂的三个代码没有一个地方把 if ... else ... 连用两遍的。
|
56
16ByUe06GJ2y3umH 2018-12-11 09:49:04 +08:00
感觉你这同事怕是对 pythonic 有什么误解吧?
Simple is better than complex. |
57
myyou 2018-12-11 09:56:09 +08:00
我喜欢第三种
calculate_func, task_id = ("rollback", sql_data.get("task_id", "") ) if has_data else ("calculate", sin_id) |
58
zqguo 2018-12-11 09:59:03 +08:00
我喜欢第二种,简洁。
|
59
xia0pia0 2018-12-11 10:04:34 +08:00
第二种是在 python 里确实是很常见的写法。重要的是风格要统一,不要多种风格,看得头疼。
|
60
TrickWu 2018-12-11 10:08:32 +08:00
第二种,写多了一眼就看明白
|
61
karllynn 2018-12-11 10:10:30 +08:00
这里显然应该直接 return
两者相比第一种好一点,因为只用判断一次 |
62
crawl3r 2018-12-11 10:16:08 +08:00
我会写成这样
``` return (sql_data.get("task_id", ""), "rollback") if has_data else \ (sin_id, "calculate") ``` |
63
lozzow 2018-12-11 10:21:59 +08:00 via iPhone
第一种适合写公司项目吧,毕竟看的人多,第二种其实写多了,看起来要比第一种舒服一些
|
64
rocketman13 2018-12-11 10:22:13 +08:00
分情况,你这种情况我觉得第一种更好,虽然我也经常被同事喷为什么不写一行解决。。。。
|
65
Felldeadbird 2018-12-11 10:23:52 +08:00
这个需要看复杂度,
如果纯粹是 if ( 1 = 1) 这种非常短的,不用过多猜想,用第一和第二都可以。 但是在复杂的业务环境下,第一种会对于维护 和 阅读有很好的帮助。 |
66
yiplee 2018-12-11 10:30:44 +08:00
简单点好 第一种
|
67
lihongjie0209 2018-12-11 10:33:42 +08:00
我倾向于不用 Python
|
68
houshuu 2018-12-11 10:38:04 +08:00
我选择第一种, 以后维护方便.
|
69
wlsnx 2018-12-11 10:39:12 +08:00
has_data 出现两次,这两种写法里很明显第一种更好。
如果一定要用第二种写法,可以参考 54 楼和 59 楼的写法,注意不要遗漏括号。 |
70
Vegetable 2018-12-11 10:46:02 +08:00
同一个变量两次作为 if 的条件,怎么可能用第二种,为了 pythonic 牺牲可读性就忍了,难道还要牺牲性能吗?
很多时候 if 的条件不是存在内存里的,而是 computed 属性,比如 @property,习惯了这种写法岂不是找骂... 千万不要让 pythonic 和 zhuangbility 划等号. |
71
est 2018-12-11 10:52:55 +08:00
第一种更有可扩展性。
|
72
lauix 2018-12-11 10:53:10 +08:00
以前用第一种,现在看实际情况会采用第二种(三元表达式)
|
73
hjq98765 2018-12-11 10:55:26 +08:00
@liyoubin37 就是用 has_data 做索引呗?
|
74
tiedan 2018-12-11 10:57:20 +08:00
感觉都不是太好,应该减少那两个临时变量的出现。原来实习的时候曾经写了类似滥用临时变量的代码,被痛批
|
75
wingspread 2018-12-11 11:29:21 +08:00
第一种写法,可读性强,逻辑清晰
|
76
eamon666 2018-12-11 11:36:58 +08:00
第一种
|
77
Linxing 2018-12-11 11:44:52 +08:00
看情况把 比如获取一些参数 做一些简单的判断 param = 'something' if param is None else param 不然判断一大堆
|
78
imn1 2018-12-11 11:53:06 +08:00
第二种只是三元式变形而已,而且我不喜欢多次判断同一个条件
多次判断同一个条件不一定获得相同状态的,只不过此处没问题而已 如果预想(期望)所有判断都是返回相同状态的话,逻辑上不应这样写 |
80
SaltyFishMo 2018-12-11 12:17:55 +08:00 via Android
@cgsv
|
81
Leigg 2018-12-11 12:20:35 +08:00 via iPhone
如果你们写的代码不用再维护了,怎么简洁怎么来。
|
82
xuboying 2018-12-11 12:20:51 +08:00
@liyoubin37 #22 : @SaltyFishMo #34 说的对,你的例子有两大缺点,见 http://book.pythontips.com/en/latest/ternary_operators.html
|
83
aliao0019 2018-12-11 12:24:41 +08:00
这两个选第一种是因为要用来判断的是一个条件而不是两个。
但如果把下面那种改成 ```return (xx, xx ) if statement else (xxx, xxx ) ``` 那我就会选它 |
84
laike9m 2018-12-11 12:34:32 +08:00
都不够好
``` def xxxx(ph, sin_id): with OracleConnect(xxxx) as db_oracle: sql = u"xxxxx" has_data, sql_data = db_oracle.get_one(sql) if has_data: return sql_data.get("task_id", ""), "rollback" else: return sin_id, "calculate" ``` |
85
laike9m 2018-12-11 12:38:38 +08:00
|
86
swulling 2018-12-11 13:00:23 +08:00 via iPhone
你同事是不是对 Pythonic 有什么误解? Pythonic 不是去用 Python 特有的语法,让他去读 Zen of Python 吧
Readability counts |
87
24bit 2018-12-11 13:06:01 +08:00
第一种
|
88
j2gg0s 2018-12-11 13:40:34 +08:00
@vexplain 为什么会和 if else 连用两边有关系?
最初问题的纠结点不是在于要不要用 A if B or C 这样的表达方式吗? 随后找的例子哪里不合适? 反对这个 ``` calculate_func, task_id = ("rollback", sql_data.get("task_id", "")) if has_data else ("calculate", sin_id) ``` 反对的是强行把两行代码写成一行 |
89
iAcn 2018-12-11 13:46:21 +08:00
个人比较喜欢第一种,逻辑清晰
|
90
16ByUe06GJ2y3umH 2018-12-11 13:54:26 +08:00 1
@j2gg0s #88 哈哈,你这么说就没啥毛病了。
咱们出发角度不一样, 我认为问题的纠结点不是 A if B or C 这样的表达方式, 而是一些简单的单次判断用 A if B or C, 多次的判断同一值就要不要强行写成这种单行形式。 所以咱们最终会的观点是一致的。over。 |
91
Janusio 2018-12-11 13:59:02 +08:00
无 bug 第一,清晰简洁可读性第二,复杂深奥往后。0.0
|
92
stzz 2018-12-11 13:59:39 +08:00
@xiangyuecn #10 兄弟,好奇去 github 看了眼,被打的太惨了啊
|
93
windvans 2018-12-11 14:08:20 +08:00
我选第一,可读性可维护行还是要强一点
|
94
loryyang 2018-12-11 14:25:01 +08:00
我喜欢 1,而且我觉得 2 这个 if 语法糖就不应该出现
|
95
xiangyuecn 2018-12-11 14:27:02 +08:00
@stzz 嘿嘿 还是自己家的代码好 花样写都可以
|
97
Bardon 2018-12-11 16:17:52 +08:00
一切的炫技都要被打倒,如果是多人参与的项目。
|
98
cnt2ex 2018-12-11 20:21:06 +08:00 1
@j2gg0s
我个人倾向于第一次给变量“赋值”看作声明,但是由于 python 中的特殊规则(不需要指明类型)并且没有类似 let 这样的关键字,所以“赋值”和“声明”使用了相同的语法,结果导致了没有声明只有赋值。不过这只是我个人的观点。 我说的按照作用域规则也是根据其他语言的习惯,因为我觉得块作用域是个好东西,所以在 python 里也遵从这样的规则(即使 python 本身并没有 if 作用域)。 以下是题外话,第二种写法,我觉得应该是函数式写法。因为函数式编程语言里通常不希望(甚至不允许)使用有副作用的语句,所以即使由于作用域规则写成: calculate_func = "calculate" task_id = sin_id if has_data: calculate_func = "rollback" task_id = sql_data.get("task_id", "") return task_id, calculate_func 这种先设置一个值,然后再根据条件修改一个值这样的写法是在函数式语言里不被提倡的。但是这种在实际应用中却十分常见,所以很多函数式的语言都会让 if 变成一个可以返回值的表达式。python 这种风格应该也是从函数式里借鉴过来的。 |
99
j2gg0s 2018-12-11 22:24:10 +08:00
@cnt2ex FP 实在是走的有点远,X if C else Y 其实只是起个三元表达式的作用,Python 的表现形式比较特殊,动态语言、若类型又让他的表达能力非常强,所以在 Python 里面用的比较多。
但真只是个三元表达式,还非要被一堆人说很难理解。 https://www.python.org/dev/peps/pep-0308/#adding-a-conditional-expression |
100
kkk33 2018-12-12 01:32:47 +08:00 via iPad
“第一种写法,比较直接,清晰明了” 的依据是什么?
|