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
vicalloy
V2EX  ›  Python

你们的 Python 代码加不加 Type Hints

  •  
  •   vicalloy ·
    vicalloy · 2023-09-05 14:44:27 +08:00 · 6536 次点击
    这是一个创建于 475 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现在成熟一些的 Python 库都是有 Type Hints 。就我而言,新写的代码基本上都会加。加上后 IDE 可以自动补全,配合 mypy 检查出一些潜在的错误。
    在我看来,在程序开始变复杂时,应当让 IDE 和编译器能尽可能的发现更多的问题。如果要用 Python 写一些复杂一些的程序,Type Hints/代码检查/单元测试都是必不可少的。
    近期看到有人说“类型注解会增加看代码的心智负担”。感觉就如何注释写多了会增加心智负担一样,无法理解。再者 Python 里大多的类型其实都是可以自动推导,除了函数的输入/输出参数,要手动注明的其实并不多。

    如果自己写一些小工具,自然是怎么方便怎么来,Type Hints 加不加都无所谓。如果是给其他人用的公共库,不加 Type Hints 对使用者很不友好。
    第 1 条附言  ·  2023-09-06 09:11:28 +08:00
    看来大多人还说支持 Type Hints 。这个言论来自 CPyUG 的 Telegram 群组。CPyUG 作为国内最早的 Python 组织,整体水平应当比较高才对。一堆人说不应该加 Type Hints ,让我觉得很迷幻。
    69 条回复    2023-10-04 11:46:05 +08:00
    TuringGunner
        1
    TuringGunner  
       2023-09-05 14:46:28 +08:00
    反正我现在写代码习惯性的就加上了
    hsfzxjy
        2
    hsfzxjy  
       2023-09-05 14:48:38 +08:00   ❤️ 3


    p.s. python 3.12 即将引入的 PEP 695 会让 type hint 的写法更加方便

    https://peps.python.org/pep-0695/
    inhzus
        3
    inhzus  
       2023-09-05 14:57:47 +08:00
    加,自己写的代码自己爽
    NoOneNoBody
        4
    NoOneNoBody  
       2023-09-05 15:06:21 +08:00   ❤️ 1
    我这种隔夜忘,不单写 type hints ,还写 __doc__
    除非函数很简单,一眼就知道类型和它做什么

    对我来说,离不开 pyright 了
    BBCCBB
        5
    BBCCBB  
       2023-09-05 15:09:58 +08:00
    不加等后面维护时看代码恼火
    julyclyde
        6
    julyclyde  
       2023-09-05 15:10:25 +08:00
    我后来特地整改过一轮,加上了
    不过我发现有些似乎不太好写,比如我的函数会 yield 一堆结果出来

    之前还特地查过,现在又忘了怎么表达 yield 了
    yunyuyuan
        7
    yunyuyuan  
       2023-09-05 15:33:13 +08:00
    写,但是体验完全比不上 Typescript ,Generic 总是用不明白
    alexsz
        8
    alexsz  
       2023-09-05 15:34:26 +08:00
    以前不写,现在开始写了
    yunyuyuan
        9
    yunyuyuan  
       2023-09-05 15:34:35 +08:00
    @hsfzxjy 这个不错
    lambdaq
        10
    lambdaq  
       2023-09-05 15:38:26 +08:00
    出参入参看心情加一下。别的不加。
    DOLLOR
        11
    DOLLOR  
       2023-09-05 15:44:53 +08:00
    我写 python 基本上都加 type hints 了。
    甚至写 js 都要加 jsdoc + ts-check 。
    craiiz
        12
    craiiz  
       2023-09-05 17:10:18 +08:00
    加了真的很爽
    pengtdyd
        13
    pengtdyd  
       2023-09-05 17:11:34 +08:00
    python 如果加了 type hints 那还是 python 吗?那不成 java 了
    XueXianqi
        14
    XueXianqi  
       2023-09-05 17:15:20 +08:00
    加,都加,入参出参的 Type Hints 、doc-string 、Demo 都加上

    举个栗子:

    ```python
    from decimal import Decimal
    from typing import Union

    DOT: str = "."
    ERROR_TIP: str = "numbers 元素必须为数字类型"


    def x_round(
    num: Union[int, float, Decimal],
    bit: int = 2,
    ) -> Decimal:
    """
    提高精度的四舍五入

    >>> round(num=1.115) # no
    1.11

    >>> round(num=1.125) # yes
    1.13

    >>> x_round(num=1.115) # yes
    1.12

    >>> x_round(num=1.125) # yes
    1.13

    :param num: 需要四舍五入(严格意义上,是:四舍六入五成双)的数字
    :param bit: 精确到小数点后几位
    :return: 四舍五入后的数字
    :raise ValueError: bit 必须大于等于 0
    """

    if bit < 0:
    raise ValueError("bit 必须大于等于 0")

    _times: int = 10 ** bit # 倍数(功能等同于保留几位小数)

    rough_num: float = round(num * _times) / _times

    return Decimal(str(rough_num))
    ```
    XueXianqi
        15
    XueXianqi  
       2023-09-05 17:18:37 +08:00   ❤️ 1
    @pengtdyd
    Python 代码加上 Type Hints ,看起来虽然没有那么 Pythonic 了,虽然更加费时了,但是可读性、可维护性大大增强了,在我看来,还是很有必要的
    cmdOptionKana
        16
    cmdOptionKana  
       2023-09-05 17:30:16 +08:00
    加过,还是比较麻烦,小项目没必要。
    LitterGopher
        17
    LitterGopher  
       2023-09-05 17:38:27 +08:00
    新代码都是基本加上的,旧代码啥时候改到那个地方再改。

    没有处于可维护性,可读性这一类高大的原因,而是很简单的加上之后 IDE 提示更加友善。
    fcfangcc
        18
    fcfangcc  
       2023-09-05 17:43:56 +08:00
    wzw
        19
    wzw  
       2023-09-05 18:48:58 +08:00
    小东西随便了, 要是是项目一定要加, 重要的我就上 Golang
    asmoker
        20
    asmoker  
       2023-09-05 19:23:27 +08:00 via Android
    不写,我写 Python 就是指为了省事儿,自然语言似的,文思如尿崩,要是写 type hints 还不如用 go
    fzls
        21
    fzls  
       2023-09-05 19:23:40 +08:00
    加,这样后面 lint 工具可以帮忙检测不少问题
    highf4324
        22
    highf4324  
       2023-09-05 21:17:44 +08:00
    当然要加,不然之前的代码维护起来将是灾难。
    zictos
        23
    zictos  
       2023-09-05 21:28:06 +08:00
    同一个变量进行多次赋值,习惯用同一个变量名,懒得用太多名字。
    比如
    a = '1'
    a = int(a)
    a = a + 5
    a = str(a)
    zlstone
        24
    zlstone  
       2023-09-05 21:52:27 +08:00
    现在看别人不加 typing 的代码,真的是太恶心了,受不了
    Leviathann
        25
    Leviathann  
       2023-09-05 21:56:04 +08:00
    @zictos 这叫 shadowing
    molika
        26
    molika  
       2023-09-05 21:59:25 +08:00
    必须加。
    zictos
        27
    zictos  
       2023-09-05 22:12:08 +08:00
    @Leviathann #25 实际只会更复杂,这只是简单的例子。变量命名尽量简单,有一个基础名称就行,之后多次操作时都使用同一个名称,但中途对象和类型可能早就改变了。如果一个名称只能代表一个类型,那繁琐程度无法想象。
    zictos
        28
    zictos  
       2023-09-05 22:50:16 +08:00
    @zictos #27 补充一下,如果只是在函数参数上注明类型和返回值的类型,那还好。如果限制一个变量只能一个类型,那真的很繁琐。但是如果不完全限制变量的类型,IDE 应该还是不能比较完美地检查的吧!
    LinYaXuan
        29
    LinYaXuan  
       2023-09-05 23:05:35 +08:00
    有什么工具能检查是否有代码缺少 typing 的吗?
    Trim21
        30
    Trim21  
       2023-09-05 23:21:55 +08:00   ❤️ 2
    @LinYaXuan #29 mypy no-untyped-def 设置
    lanlanye
        31
    lanlanye  
       2023-09-05 23:54:06 +08:00
    pylance 设置里打开显示类型推导,会在 IDE 中展示推导出的类型,实际需要添加的就很少了,看代码也方便。
    Donahue
        32
    Donahue  
       2023-09-06 00:06:05 +08:00
    必须加,加了之后写代码可以享受编辑器的自动补全功能,为什么不加呢?哪怕只是一个小脚本我也加,因为自动补全太方便了
    HankLu
        33
    HankLu  
       2023-09-06 00:27:21 +08:00
    肯定不加啊,这不是没事找事吗
    jackmod
        34
    jackmod  
       2023-09-06 00:30:56 +08:00
    但凡需要 pip install 的项目就尽可能加,弄得像强类型语言那样。
    有 pylance 这类的好用插件帮助并不需要多少精力。
    pylance 给出的 warning 也要用正确的方式消掉,这期间还能发现一些隐藏 bug 。
    so1n
        35
    so1n  
       2023-09-06 01:35:58 +08:00
    尽量加
    levelworm
        36
    levelworm  
       2023-09-06 02:19:33 +08:00 via Android
    能加就加。不过有些的确也蛮烦的,比如说要写成 a.b.c 这种的。
    wizardyhnr
        37
    wizardyhnr  
       2023-09-06 06:05:31 +08:00
    尽量加吧,养成习惯,Cython, Mojo 等一众语言都是依赖静态类型来加速的,养成语法习惯以后用这些进一步优化性能就很顺,不属于沉没成本
    NoAnyLove
        38
    NoAnyLove  
       2023-09-06 06:47:10 +08:00
    个人觉得没有 type hints 的代码才是难以阅读。“增加心智”负担是什么鬼?这是谁的观点啊?加 type hints 影响他 san 值了?加多了要克苏鲁化?
    bianhui
        39
    bianhui  
       2023-09-06 08:06:24 +08:00
    尽量不加,如果加了那你比别人价值高在哪?让项目离开自己难以维护,从而在公司站住脚。
    jjx
        40
    jjx  
       2023-09-06 08:16:44 +08:00
    看你应用模式
    企业 crud , 数据类型主要来自 db , 字符串是主要形式, 个人认为加不加没有实在意义

    其次是这语言本身, 类型是属于后加上去的,怎么用都不怎么舒服


    真要这样, 不如直接用静态语言
    mobpsycho100
        41
    mobpsycho100  
       2023-09-06 08:21:27 +08:00
    稍微复杂一点的程序就要加了, 写 script 一般不加
    zhishixiang
        42
    zhishixiang  
       2023-09-06 08:27:57 +08:00
    刚开始写时不知道有这东西,都是一把梭,到后面被教训了才知道有这东西
    roycestevie6761
        43
    roycestevie6761  
       2023-09-06 08:29:20 +08:00
    必须加,不加代码提示都没有,跟记事本有什么区别
    neutrinos
        44
    neutrinos  
       2023-09-06 08:52:38 +08:00 via iPhone   ❤️ 1
    不加,想加的话会换一种静态语言
    vialon17
        45
    vialon17  
       2023-09-06 08:53:53 +08:00
    那肯定要加的,python 之所以被诟病的原因之一就是 type hint ,
    而且随着版本迭代升级,py 也逐渐支持 type hint ,能够写的更加清晰明了,
    我不知道有什么理由不写。-_-||
    ps:现在常用的编译器都支持 py 的类型检测了,写上类型提示后后面再看变量很方便。
    BingoXuan
        46
    BingoXuan  
       2023-09-06 09:26:17 +08:00
    加,但 type hints 很废,做不了类型体操
    raptor
        47
    raptor  
       2023-09-06 09:51:38 +08:00
    加,加了以后易读性好多了。
    fbichijing
        48
    fbichijing  
       2023-09-06 09:52:58 +08:00
    不喜欢,因为不够简洁。

    很多参数看到参数名就能大概知道应该传进什么类型的数值进去,出错的话就 help 看一下函数注释也就知道了。

    个人比较喜欢函数注释的那种写法,当有写的必要性时就会加上。就像 requests 里面的

    # requests api.py
    ```python
    def request(method, url, **kwargs):
    """Constructs and sends a :class:`Request <Request>`.

    :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
    :param url: URL for the new :class:`Request` object.
    :param params: (optional) Dictionary, list of tuples or bytes to send
    in the query string for the :class:`Request`.
    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
    object to send in the body of the :class:`Request`.
    ```
    Davic1
        49
    Davic1  
       2023-09-06 10:00:17 +08:00
    @hsfzxjy 补充一个 pep695 具体变化的讨论贴(个人觉得新手友好一些)

    https://www.reddit.com/r/Python/comments/12f3glm/pep_695_type_parameter_syntax_has_been_accepted/
    akaHenry
        50
    akaHenry  
       2023-09-06 10:24:07 +08:00   ❤️ 1
    Type Hints 是政治正确. (就算很多人日常不加, 恐怕也装装样子鼓励他人加)

    Type Hints 当然是好, 但是有开销. (加不加, 加多少, 看具体场景/维护成本/代码生命周期, 以及你和团队会几门语言.)


    应该加:

    1. 团队(个人) 只会/只用 python 开发, typing 和 Pydantic 都用起来.

    2. 单元测试, 写起来, 至少覆盖核心链路. (这比 Type Hints 更容易保障质量和正确使用, 如果时间仅够二选一, 宁愿你写单元测试)


    少加/不加: (CPyUG 老炮的场景)

    1. 个人项目, 生命周期很短(活不久)的代码. 加了没收益.(怎么快, 怎么来)

    2. 多技能栈(Python + Rust, Go 等) 组合. 充分利用动态语言的灵活性, 少加/不加. 需要强约束/性能场景, 直接切 rust/go.

    3. 老司机, 写的代码, 可读性好. 加不加, 不影响阅读. (废话, 没有 Type Hints 之前的 10 多年, 大家照样写的飞起)

    4. 一次性的脚本, 用完就扔(厕纸代码, 活不过明天). 没必要脱裤子放屁.



    个人选择:

    1. 作为写了比较久 python 的( py2.5 开始的), CPyUG 说不加 Type Hints 的人不少. 很正常.(在很多场景, 不用, 也都对)

    2. 加当然好, 但是要平衡成本和收益. (年轻人, 容易沉迷于写太多没 转化率(不赚钱) 的代码)

    3. 我日常会加, 但保持克制. (少用和不用 Pydantic, 有开销).

    4. python 已经不是我的主力语言, 用 python 更多是为了快速糊东西和验证技术/产品原型. 一旦验证通过, 很快就会迁移到 rust, go 等重写. 所以, 写 python, 就更追求 怎么快, 怎么来. (代码活不久, 没必要写太好)


    以上来自 写了 10 多年 python 的开发者的一点看法.

    (当然, mojo 1-2 周, 就要发布了, 喜欢写 Type Hints, 来写 mojo 吧)


    免杠指南:

    我只是说了 不加/少加 的场景, 你要杠, 你对.
    mywaiting
        51
    mywaiting  
       2023-09-06 10:36:50 +08:00   ❤️ 1
    话说我用动态语言就是为了写少一点类型声明,为的是粗快猛一把梭!有这觉悟我直接换其他语言了~
    t133
        52
    t133  
       2023-09-06 10:42:43 +08:00 via iPhone
    看到**kwargs 还不注释就想骂娘了
    codeMore
        53
    codeMore  
       2023-09-06 11:19:38 +08:00
    我们维护的老项目还是基于 python2.7 的呢,不支持
    julyclyde
        54
    julyclyde  
       2023-09-06 11:34:25 +08:00
    没看懂你这句 append 的语气
    “水平应该更高才对”似乎暗示了其实并不高?
    julyclyde
        55
    julyclyde  
       2023-09-06 11:36:20 +08:00
    哦哦,明白了“少加/不加: (CPyUG 老炮的场景)”
    jjx
        56
    jjx  
       2023-09-06 12:13:44 +08:00
    你喜欢, 你觉得好你就加

    但这个同代码可读性完全不能划等号, 否则的话, 静态类型的语言的程序员都是好程序员了?

    代码的可读性还是依赖 模块划分, 命名, 代码逻辑清晰表述, 使用大家都明白的设计模式等来达成的

    有些人用 python 就是不喜欢脱裤子放屁的场合,比方说, 你明明就知道他的类型, 但一定要写类型(并且强制转换, 静态语言), 结果你一定要他写 python 也是如此, 没有意义
    sordidclown
        57
    sordidclown  
       2023-09-06 12:18:30 +08:00
    个人是加注解的。但是有个问题,假如说不加类型注释,pycharm 在推导不出来类型的时候不会提示属性和方法,也没有检查和补全,这样的话代码写起来不会很难受吗?还是说有其他办法避免这种情况发生?
    tankeco
        58
    tankeco  
       2023-09-06 12:38:33 +08:00
    遇到最多的问题是,加了 type hints 的代码换了个 python 版本跑不起来…需要我一顿改 tuple 到 Tuple…
    ksc010
        59
    ksc010  
       2023-09-06 13:00:45 +08:00
    我写的几个项目,从不打算兼容 py2 之后就开始慢慢加了
    主要是为了代码提示
    RyougiShiki
        60
    RyougiShiki  
       2023-09-06 13:05:42 +08:00
    曾经不想把动态语言写的跟 java 一样,我不喜欢 java 才转的 python 也认同 py 的设计哲学。自从用过 FastAPI 后,惊讶于类型注释和由此的参数检查、api 文件自动生成,觉得真方便。现在,我在纯 py 脚本中使用,虽然不会运行时强制,但 pycharm 会检查,相当于方法文档也挺好的。
    ch2
        61
    ch2  
       2023-09-06 13:21:43 +08:00
    新项目,多人协作的,加了有显而易见的好处
    老项目,个人 solo 的,不加也无所谓
    LokiSharp
        62
    LokiSharp  
       2023-09-06 13:28:57 +08:00
    写了就当注释呀
    BeautifulSoap
        63
    BeautifulSoap  
       2023-09-06 13:30:44 +08:00
    反正已经不用 python 写大项目了,小项目或者脚本我是不太加的,主要是 python 这 type hint 实在写起来难受死了
    给 List 之类基础类型写个 type hint 还得导包
    给函数指针写 type hint 要导入 Callback ,然后 Callable[[typ1, type2 ..., type3], type3] 这样不光看得闹心我写得也是闹心,尤其一个入参出参复杂点的函数
    而且 idea/pycharm 不知为什么经常 type hint 工作不正常,其他地方明明都加了 type hint 了,一看创建的变量类型 Any ,摔
    反正体验说不上太好
    sweat89
        64
    sweat89  
       2023-09-06 19:38:35 +08:00
    不加啊,难道各位忘了用 python 的初衷?
    人生苦短,我用 python
    xgdgsc
        65
    xgdgsc  
       2023-09-06 19:51:48 +08:00 via Android
    不加,又不像 julia 加了能提升性能
    julyclyde
        66
    julyclyde  
       2023-09-07 14:59:30 +08:00
    @tankeco tuple 到 Tuple 是什么情况啊?
    tankeco
        67
    tankeco  
       2023-09-07 20:34:30 +08:00   ❤️ 1
    @julyclyde python3.9+可以写 list[int], tuple[int],但<=3.8 需要写 import List, Tuple. 现在最流行的 python 版本就是 3.8-3.10 ,所以经常遇到代码,明明其实是可以支持 3.8 的,只是因为 type hint 不支持 3.8 ,就非常令人难受
    VforVendetta
        68
    VforVendetta  
       2023-09-11 10:02:48 +08:00
    目前没加
    xzm429438709
        69
    xzm429438709  
       2023-10-04 11:46:05 +08:00 via Android
    我想加,怕自己写了代码,放假回来忘记逻辑了,但是有时候自私点又不想加,不想别人太容易知道我的逻辑,就不加
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1348 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 17:24 · PVG 01:24 · LAX 09:24 · JFK 12:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.