阅读 Python 代码的困难

2021-10-11 11:47:05 +08:00
 shyrock
已经轻度使用 python 两年了,始终觉得阅读别人的 python 源码会有些困难。
比如在一个函数中,很难找到传入参数的定义,导致难以精确理解本函数的功能。
作为对比,以前用 c++,所有变量和参数都明确声明了类型,可以很精确地定位到该类型地定义。用于辅助理解当前函数的功能。

是我没找到方法?还是这就是 python 的缺陷?
3551 次点击
所在节点    Python
18 条回复
xmt328
2021-10-11 14:05:17 +08:00
我感觉这是弱类型语言的通病
我也一直不习惯
shyrock
2021-10-11 14:15:21 +08:00
@xmt328 #1 然而 python 是强类型的。。。
AlexLokhart
2021-10-11 14:34:07 +08:00
我觉得应该算“缺陷”吧,毕竟整体看起来就像是伪代码,如果别人有良好的代码习惯不算是问题,如果对方命名用 abc,ijk,那就很麻烦,python 3 虽然可以指定类型 def do_something( name : type ) -> return_type,不过不能期待别人也那么做了
abersheeran
2021-10-11 14:39:49 +08:00
是的,这正是动态类型语言的弱点。所以 JavaScript 有了 TypeScript,Python 有了 Type hint 。

Type hint 的例子 https://github.com/abersheeran/baize,几乎没有 Any,很接近静态类型语言了,读起来应该会比较简单。
shyrock
2021-10-11 15:00:18 +08:00
@AlexLokhart #3 不知道 pycharm 一类的 IDE 有没有办法从代码中推断出类型。
Jwyt
2021-10-11 21:06:00 +08:00
@shyrock 没有的 解释器也是运行时才能知道吧,只能祈祷对方的 Type hint 比较完善。。
princelai
2021-10-12 09:39:52 +08:00
@shyrock #5 没办法推导,动态类型就这样,type hint 也是写给人看的,编译器会忽略

ls = [1,"2","c"]
for x in ls:
pass

x 的类型没法提前判断,即使提前声明,运行时也可以任意更改
lppdao
2021-10-12 10:13:56 +08:00
@shyrock 我也有这样的困惑, 特别是复杂结构的参数, 没有文档根本不知道怎么搞, 以至于要看 c++的版本来确定类型.... 不知道你有没有找到什么好办法
2i2Re2PLMaDnghL
2021-10-12 11:05:30 +08:00
@shyrock 只能从已知的开始推断,依赖于有 stub 的模块( builtin 和 std 应该都有 stub 了?)。好在,许多常用的模块新增了 stub (可能单独成包)推断能力也不强。
julyclyde
2021-10-12 17:20:19 +08:00
不过参数的定义即使没有类型也能看明白吧
shyrock
2021-10-12 18:16:20 +08:00
@julyclyde #10 怎么做到的?
rationa1cuzz
2021-10-12 19:45:49 +08:00
动态类型的通病,无解,不过 py3 都支持入参类型的注释,类似
def demo(i:int,a) -> bool:错的话解释器都会有高亮
featureoverload
2021-10-12 21:51:05 +08:00
1. 虽然很高级的工程师(对程序理解很深)并不需要很多 type hints ;但 type hints 确实有是要比没有好得多的。

2. Python 可以用很短的代码表达很多的内容(知识)。所以有些代码不具备相关知识自然是看不懂的。

比如,没有掌握递归知识的初学者,看递归函数是很难理解的:

def fib(n):
....if n < 0:
........raise ValueError("can't be negative")
....elif n <= 1:
........return n
....return fib(n-2) + fib(n-1)

(递归不是“内容很多”的知识,所以其它语言也可以用很短的代码实现,这里是强调掌握不掌握这个知识对代码理解的帮助问题)

比如如果没有了解数据结构的特点和一点训练,是很难看懂这段代码:

def find_duplicates(list_):
....existed, duplicate = set(), set()
....for item in list_:
........if item in existed:
............duplicate.add(item)
........else:
............existed.add(item)
....return duplicate

duplicates = find_duplicates(values)


有些疯狂的孩子甚至可以去掉上面这个函数,"一行"得到结果(为了方便阅读,我把调用函数的参数换行):

duplicates = reduce(
....lambda case, item: (case[item in case[False]].add(item), case)[-1],
....values,
,,,,{True: set(), False: set()}
)[True]

所以,要说不好读,确实很多情况都会不好读。
这取决与每个人对软件的理解程度。
jaredyam
2021-10-12 22:29:26 +08:00
我的两点看法:
1. 原作者代码具有较高可读性和包含适当或完备的 type hint 肯定是提升阅读体验,这也正是多数 Python 项目的「加分项」;
2. Python 项目很多是算法驱动,很多时候对一些数理逻辑的理解更费时间,项目作者有时候也未必对代码本身精益求精;
dayeye2006199
2021-10-13 01:22:32 +08:00
多人协作需要 type hints 和 docstring,否则神仙难救。

可以在 linting 阶段加入 mypy 或者 pyre 这样的类型检查器,让大家尽量不全类型信息。
Mark24
2021-10-14 16:24:06 +08:00
个人观点:

其实类型注解意义不大,加了反而对动态语言是个约束,丧失了动态语言的优势

动态语言,需要配合单测。单测的意义跟类型是一样的,甚至比类型还牛一点。理论上单测应该起到各种类型输入的 例子的作用。

但是现实中业务仔们没空写。
shyrock
2021-10-14 16:54:51 +08:00
@Mark24 #16 不同意单测能替代类型提示。对于读代码的人来说,一段简单的代码因为类型不清楚而无法理解背后的意图,再去看单测也很难理解。这就导致代码的维护变得极为困难。

现代代码,最重要的是让人容易读懂。
shm7
2021-11-21 18:41:39 +08:00
参数的定义,写得好的库,都有类似 pythondoc 的实现,怎么会不好读呢。我看到也就是一些底层实现非 Python 的才会有这类问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/806996

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX