V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
shyrock
V2EX  ›  Python

阅读 Python 代码的困难

  •  
  •   shyrock · 2021-10-11 11:47:05 +08:00 · 3522 次点击
    这是一个创建于 1143 天前的主题,其中的信息可能已经有所发展或是发生改变。
    已经轻度使用 python 两年了,始终觉得阅读别人的 python 源码会有些困难。
    比如在一个函数中,很难找到传入参数的定义,导致难以精确理解本函数的功能。
    作为对比,以前用 c++,所有变量和参数都明确声明了类型,可以很精确地定位到该类型地定义。用于辅助理解当前函数的功能。

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

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

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

    x 的类型没法提前判断,即使提前声明,运行时也可以任意更改
    lppdao
        8
    lppdao  
       2021-10-12 10:13:56 +08:00
    @shyrock 我也有这样的困惑, 特别是复杂结构的参数, 没有文档根本不知道怎么搞, 以至于要看 c++的版本来确定类型.... 不知道你有没有找到什么好办法
    2i2Re2PLMaDnghL
        9
    2i2Re2PLMaDnghL  
       2021-10-12 11:05:30 +08:00
    @shyrock 只能从已知的开始推断,依赖于有 stub 的模块( builtin 和 std 应该都有 stub 了?)。好在,许多常用的模块新增了 stub (可能单独成包)推断能力也不强。
    julyclyde
        10
    julyclyde  
       2021-10-12 17:20:19 +08:00
    不过参数的定义即使没有类型也能看明白吧
    shyrock
        11
    shyrock  
    OP
       2021-10-12 18:16:20 +08:00
    @julyclyde #10 怎么做到的?
    rationa1cuzz
        12
    rationa1cuzz  
       2021-10-12 19:45:49 +08:00
    动态类型的通病,无解,不过 py3 都支持入参类型的注释,类似
    def demo(i:int,a) -> bool:错的话解释器都会有高亮
    featureoverload
        13
    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
        14
    jaredyam  
       2021-10-12 22:29:26 +08:00
    我的两点看法:
    1. 原作者代码具有较高可读性和包含适当或完备的 type hint 肯定是提升阅读体验,这也正是多数 Python 项目的「加分项」;
    2. Python 项目很多是算法驱动,很多时候对一些数理逻辑的理解更费时间,项目作者有时候也未必对代码本身精益求精;
    dayeye2006199
        15
    dayeye2006199  
       2021-10-13 01:22:32 +08:00
    多人协作需要 type hints 和 docstring,否则神仙难救。

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

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

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

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

    现代代码,最重要的是让人容易读懂。
    shm7
        18
    shm7  
       2021-11-21 18:41:39 +08:00
    参数的定义,写得好的库,都有类似 pythondoc 的实现,怎么会不好读呢。我看到也就是一些底层实现非 Python 的才会有这类问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3350 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:01 · PVG 20:01 · LAX 04:01 · JFK 07:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.