推荐学习书目
› 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
onice
V2EX  ›  Python

Python 有必要自己写类型判断吗?

  •  
  •   onice · Mar 15, 2020 · 9980 views
    This topic created in 2432 days ago, the information mentioned may be changed or developed.

    可能是因为我是从 Java 转 Python 的,我把 Python 当作是我的第二语言。

    总所周知,Java 是强类型的语言,传参的时候类型错误编译是不会通过的。

    为了让 Python 能像 Java 那样,我的想法是在方法开始的地方自己手动做类型判断。

    类似这种:

    def getHTML(url):
    	if type(url) != str:
            raise TypeError("url 参数只能是字符串"")
    

    这么做的目的是为了防止传入的参数类型不正确。但是转念一想,我在注释里面写明也可以,这么做有必要吗?

    Supplement 1  ·  Mar 16, 2020
    感谢各位大佬的解答。我觉得快速赋值难道不是 Python 的优势吗,我觉得我是以 Java 编程的思想在去写 Python。
    77 replies  •  2020-04-09 18:15:04 +08:00
    JCZ2MkKb5S8ZX9pq
    JCZ2MkKb5S8ZX9pq
    Mar 15, 2020
    1
    可以了解下 assert,不过大多数情况下我是不写的。
    westoy
    westoy
    Mar 15, 2020
    2
    3.5 开始就有 type hints 了啊

    @JCZ2MkKb5S8ZX9pq assert 语法在 python -O 的时候会跳过的, 不是运行时判断的
    widewing
    widewing
    Mar 15, 2020 via Android
    3
    def getHTML(url:str):
    blahblah
    imn1
    imn1
    Mar 15, 2020
    4
    按易入难出原则的话,是要写的
    但如果都商量好了格式,或者 API 固定,就没必要了
    vicalloy
    vicalloy
    Mar 15, 2020
    5
    这样做只有运行时才会报错。如果是运行时报错,这个提示不会比不做类型检查的报错清楚多少。
    python 3.5 开始支持 type hints,之前的版本也有相应的库支持类似 type hints 的检查。
    这样做完全没有必要。
    PTLin
    PTLin
    Mar 15, 2020
    6
    真在意类型的话可以用装饰器来实现参数类型的校验,而且 Python 是动态强类型语言。
    https://paste.ubuntu.com/p/RSWXVt5pZP/
    wuwukai007
    wuwukai007
    Mar 15, 2020
    7
    写只是为了方便维护,仅此而已。
    QingXuJiaZhi
    QingXuJiaZhi
    Mar 15, 2020
    8
    既然用了 python,建议尽量先习惯一下动态语言的思维方式,曾经盛极一时的 python2 也没有 type hint,照样能干活。

    不然多学一门语言有啥意义呢。

    (另外你用 type hint, 但你看别人的代码多数没有 type hint, 总的来说还是要转变思维的)
    ClericPy
    ClericPy
    Mar 15, 2020❤️1
    9
    type hints 配合 mypy, 代码没执行就看到一大堆错误类型的报错

    type hints 配合 pydantic, 类型不对的会尝试转换, 转换失败会报错, 类似于 var: int = '123' => 123, path: Path = '/' => Path('/')
    zhengxiaowai
    zhengxiaowai
    Mar 15, 2020
    10
    编程理念不同而已,常见的做法有三种

    1、利用异常机制自己在错误时候抛出异常,这时候抛出的异常的函数往往不是传入的那个函数,会导致排查困难
    2、防御式编程如果你描述的那样,这样代码写的多能够及时发现,排查简单
    3、type hint 这个会的不多,写好的更少,依赖工具检查需要高版本 python

    从开源项目来看 方式 2 用的比较多,方式 3 是趋势
    ManjusakaL
    ManjusakaL
    Mar 15, 2020❤️5
    11
    一大堆推荐用 type hint 的,我简直乐的不行

    1. Type Hint 3.5 之后的特性,现在还有很多公司的 codebase 在 2.7 吧?拿头用 PEP484 ? 写注释? backport 只支持了基本类型

    2. Type Hint 的生效,极其依赖 CI 流程,你不用 mypy 之类的工具,直接暴力上线,有蛋用。。。人家是 static analysis 而不是 runtime analysis

    3. 关键位置做防御式编程,是个很好的习惯
    ipwx
    ipwx
    Mar 15, 2020
    12
    看情况吧。不过很多一般省去类别检查,就当它是 str 或者 str-like。或者直接 url = str(url)。
    szbzhao
    szbzhao
    Mar 15, 2020
    13
    你不要理这些,先把任务完成!
    janxin
    janxin
    Mar 15, 2020
    14
    @ManjusakaL 虽然是这么说,但是也要看每个公司的情况,我猜很多用 py2 的大概后面都要换到 Java/Go 去了吧...

    另外借助运行时装饰器也是可以实现 runtime checker 功能的,比如 typeguard 之类的工具可以实现这样的功能。当然这种方案也有负面作用,借助 mypy 这类的工具也不是没价值,不过属于额外基础设施方案。

    防御编程十分有必要,无论是否是强类型语言,都需要做。
    iConnect
    iConnect
    Mar 15, 2020
    15
    @ipwx #12 楼的方式值得推荐,关键位置预防一下即可。
    love
    love
    Mar 15, 2020
    16
    那用动态语言又是何必呢
    我记得在哪看的 js 最佳实践是不建议写参数类型判断的
    janxin
    janxin
    Mar 15, 2020
    17
    @love 还有这种实践?我读书少你别骗我
    shijingshijing
    shijingshijing
    Mar 15, 2020
    18
    这是 python 的 feature,你这样写就不够 pythonic 了
    love
    love
    Mar 15, 2020 via Android
    19
    @janxin 你去看流行的 js 开源代码,没有人会检查参数类型错误。真要检查类型错误上 typescript
    yuchenyang1994
    yuchenyang1994
    Mar 15, 2020
    20
    我看到这些推荐用 type hint 的,我也乐的不行
    1. type hint != 类型检查
    2. type hint 是自己骗自己,没有编译时的语言,一切类型标注都是自己骗自己,是耍流氓
    3. 该写单测写单测
    love
    love
    Mar 15, 2020 via Android
    21
    @yuchenyang1994 你是来搞笑吗,你的意思是动态类型语言的单元测试还要测试错误的类型输入?哪个项目这么干我去膜拜一下
    jin7
    jin7
    Mar 15, 2020
    22
    就写个脚本 不用这个复杂....
    UnknownR
    UnknownR
    Mar 15, 2020
    23
    用 c#,但是理念差不多,try catch 一把梭,报错了再说

    要么直接类型转换,转不了再抛出,要么在关键的位置做判断,其他地方等异常抛出了再处理
    pabupa
    pabupa
    Mar 15, 2020 via Android
    24
    你不加类型断言,它后面还是会报错的呀……
    Applenice
    Applenice
    Mar 15, 2020
    25
    keepeye
    keepeye
    Mar 15, 2020
    26
    如果方法是给别人用,那么 1 是要加 type hints,2 是要做必要的类型检测。
    自己用的话加个 type hints 就行了,不会明知故犯
    yonoho
    yonoho
    Mar 15, 2020
    27
    我们组现在 CR 就强制要求写 type hint。对我们有用吗?有用。对于调用方更易读,对于提供方也迫使他写之前先想清楚,低级错误会少一些。type hint 和 注释的区别在于它的规范性,更容易被支持。比如 Pycharm 就支持这种静态分析,我想也应该有一些好的库可以基于 type hint 实现你的这种需求,只要套一个装饰器就可以了。
    noparking188
    noparking188
    Mar 15, 2020
    28
    必要时候我会用 isinstance 类型检查,针对可以设想到的错误场景,大部分时候是不做类型判断的,感觉那太蠢了,多了很多无多大意义的代码,我是做数据开发的,主要处理各种数据,用 py2
    之前看了下 fastapi,它用了 pydantic,觉得挺新奇的,比较有意思,不过若是开发有点规模的 web 后台服务,我会选择 java/scala, 虽然我以前上学和实习时候都是用 python 的 flask 框架
    个人觉得 type hints 一定程度上可以帮助阅读代码,写的话会带来一些困扰,既然要写明类型,那为什么还要用 Python 呢,或许绝大部分时候并不需要这个特性
    个人觉得最好的方式还是协定好开发规范,规范、详细的注释和文档真的很有帮助
    一点愚见
    noparking188
    noparking188
    Mar 15, 2020
    29
    def getHTML(url):
    """ fetch html page

    :param url:
    :type url: str
    """

    让它报错,除非你不想这个异常被抛出而中断程序,那么请提前处理
    lithbitren
    lithbitren
    Mar 15, 2020
    30
    type hints + mypy 可以在运行前解决绝大部分类型问题,这几年 TypeScript 火起来了,Python 也受到了不少影响,不过个人而言还是反对的,类型语言多的是,写 Python 还搞类型就是脱裤子放屁,一点都不 pythonic。
    sepld
    sepld
    Mar 15, 2020
    31
    可以使用装饰器,定义下接收参数的类型, 提前处理掉
    QingXuJiaZhi
    QingXuJiaZhi
    Mar 15, 2020
    32
    如果必须写 type hint, 那么为啥要用动态类型语言,动态语言被发明出来不就是为了不把类型写死,从而获得一定程度上的便利吗
    zzj0311
    zzj0311
    Mar 15, 2020 via Android
    33
    和主流程无关的代码尽量抽离,为了编辑器提示写类型标注就够了
    vicalloy
    vicalloy
    Mar 15, 2020 via iPhone
    34
    没想到这么多人反对 type hint。
    在我看来,对于常用的库 type hint 肯定是趋势。有类型注解,文档都可以少翻很多。
    虽然我懒,一般不注明类型,但有时候为了让 ide 的自动补全可以出来也会主动的加上类型注解。
    fy
    fy
    Mar 15, 2020
    35
    type hint 很有用啊,这玩意是给 IDE 看的呀!
    pcbl
    pcbl
    Mar 15, 2020
    36
    没有什么事 try except 解决不了的,如果解决不了,那一定是你 try 的不够多(楼上头像)
    zhidian
    zhidian
    Mar 16, 2020
    37
    type hint 可以让你的 IDE 给你更好的自动补全.
    metamask
    metamask
    Mar 16, 2020
    38
    或者你从一个比较高的角度去考虑这个事情,

    假如你接受的参数是来自外部或者你必须做强校验,那么你有 2 种更好的选择

    - 从 form 或者 serializer 就定义好字段类型
    - 自己做一个 validator

    这两种做法的好处是,不会让 所谓 “类型”检验的代码散落到处都是
    metamask
    metamask
    Mar 16, 2020
    39
    get_html(url)

    这个函数在使用上就默认 url 是一个 str 就好,需要做 validate 之类的话,更有意义是检测它是否是一个完整的 http 链接
    gjquoiai
    gjquoiai
    Mar 16, 2020
    40
    想写自然可以写,不写也没人逼你写_(:з)∠)_ 突出一个自由。。
    不过我觉得你需要的是 serializer/validator 这种东西
    weyou
    weyou
    Mar 16, 2020 via Android
    41
    这不是应该跟函数的用途有关么?一般写给别人用的接口函数要去 assert 检查下。自己用的内部函数为什么要检查?自己写的函数该提供什么类型的参数自己不知道么?当然在大型项目里你想让自己调试起来方便多加类型判断也是可以的。
    charlie21
    charlie21
    Mar 16, 2020
    42
    知道为什么企业级应用能用 java 就用 java 了吗?
    yuchenyang1994
    yuchenyang1994
    Mar 16, 2020
    43
    @love 运行时报错跟没报有什么区别,我就是要写鸭子类型呢?
    xingheng
    xingheng
    Mar 16, 2020
    44
    就楼主写的 sample function 而言,加或者不加类型判断都是合理的,调用出错了也不是这个方法本身的错,应该由调用方解决。
    类型判断本身是有意义的,比如如果上面方法在实现的时候是接受 str 和 list/tuple 多种数据类型的时候,类型判断就变成了逻辑问题了。
    xingheng
    xingheng
    Mar 16, 2020
    45
    不过话说回来 type hint 还是有意义的,python 写多了自然会慢慢发现这个问题。
    type hint 本身和类型检查不冲突,但是在使用 typing 或者没有用好 typing 的时候尝试类型检查一定是非常糟心的。
    ManjusakaL
    ManjusakaL
    Mar 16, 2020 via Android❤️1
    46
    @janxin yeap 防御式编程非常重要,我只是吐槽一下把 type hint 和防御式编程等价的人。BTW runtime analysis 其实是一件吃力不讨好的事,无论是 typeguard 还是其余库,都避免不了用一些 magic lib 的使用,比如 inspect,比如 typeguard 其中还用到了一些 code frame 的操作,其实在线上一般不太会允许用这样的骚操作,因为对性能的损害太大,虽然 typeguard 有 import hook 可以做一些 inspect 的预处理&缓存的操作(其实就类似编译了)但是实际上在 runtime 还是有很多操作没法避免。。比如 typeguard 对 Collections 对象的 value type 的操作,一旦非 Any,就会遍历一次,进行 check。。在线上数据量很大的情况下。。这是炸锅的节奏😂
    levelworm
    levelworm
    Mar 16, 2020 via Android
    47
    type hint 我只是用来增加可读性,这玩意毕竟 Python 并不理睬。
    levelworm
    levelworm
    Mar 16, 2020 via Android
    48
    另外楼上有一点说的很对,type hint 对 ide 有帮助,这样自己写代码也快一些。
    ManjusakaL
    ManjusakaL
    Mar 16, 2020 via iPad
    49
    ManjusakaL
    ManjusakaL
    Mar 16, 2020
    50
    @love 如果说上面那个例子是测试结构本身的特性,不严谨的话,那么我肤浅的认为这个 https://github.com/pallets/werkzeug/blob/master/tests/test_routing.py#L802 更能算对输入类型做单测?要求传入 List,否则抛异常

    Celery/Django 这样的例子还不少,要不我再去给大佬找几个来请大佬过过目,品一品,评一评?
    jjx
    jjx
    Mar 16, 2020
    52
    type hint 很有意义

    用过 typescript 就知道了

    不过 python2 的坑 不容易出啊

    不知道 python2 还会有更好的方案没有, 在注释中写 这个完全不是一回事情啊 感觉不对
    Trim21
    Trim21
    Mar 16, 2020 via iPhone
    53
    @jjx 是不是可以写 pyi…
    benyur
    benyur
    Mar 16, 2020 via Android
    54
    我推荐一个思路,如果你是用 python3.5 以上版本,可以看看 pydantic 库,程序员只做类型声明,库帮你做类型检查,其实也是用了 python 的 type hint 特性。
    janxin
    janxin
    Mar 16, 2020
    55
    @ManjusakaL 起床过于早了啊....

    确实性能退化是最大的负面作用,选择需要根据具体的情况进行取舍
    RHxW
    RHxW
    Mar 16, 2020
    56
    @benyur
    这个东西看起来好像很 6 哦~
    lithiumii
    lithiumii
    Mar 16, 2020 via Android
    57
    py 的风格应该是要么不写要么 try except TypeError,要么你就全面 type hint
    love
    love
    Mar 16, 2020 via Android
    58
    @ManjusakaL 你这些不都是业务要求类型检测?为啥不无脑对所有参数检测?你的意思不是要对所有参数检测吗?
    SteveAlan
    SteveAlan
    Mar 16, 2020 via iPhone
    59
    要不你去看看 py 一些比较出名的库?看看人家怎么做的
    bnm965321
    bnm965321
    Mar 16, 2020
    60
    防御性编程是没错的,不过不是每个函数每个参数都要进行防御
    vkhsyj
    vkhsyj
    Mar 16, 2020
    61
    可以用 type hint
    iceking
    iceking
    Mar 16, 2020
    62
    有些场景要做,比如在向 mongo 塞数据时,类型错误就有脏数据了,当然也可以借助 odm 来处理。有的地方你不做,等着程序自己报错,外面捕获也行。要自己定义错误,就自己抛。
    ManjusakaL
    ManjusakaL
    Mar 16, 2020 via Android
    63
    @love 大佬你之前可不是这么说的噢

    > 你是来搞笑吗,你的意思是动态类型语言的单元测试还要测试错误的类型输入?哪个项目这么干我去膜拜一下

    这不给你找了几个项目嘛
    Torpedo
    Torpedo
    Mar 16, 2020
    64
    还是一定程度上有必要的。特别是你写一个大家都用的模块。传参检测可以防止人家传错误的参数。虽然运行时,至少调试的时候运行到这里可以看到。
    tobeyouth
    tobeyouth
    Mar 16, 2020
    65
    比较复杂的类型建议写上 hints,如果还在 2.7,我觉得注释或通过 schema 验证可能算是个解决方法。
    否则,一个嵌套多层的 dict / list,真的太崩溃了。
    oahebky
    oahebky
    Mar 16, 2020
    66
    按自己倾向写或者不写。
    等你 Python 代码写多了,自然能得到一个到底写还是不写的准确结论。
    如果你 python 代码一直没怎么写,那么也不需要去硬遵守应该写或者不写的结论。

    因为这个东西无关紧要。有个一年多经常写 Python 代码的人(写的很多的前提下),便可以在需要的地方写,不需要的地方不写。
    大多数情况下是不需要写的,当你不确定需不需要写的时候也是不用写的。
    TestOpsJarstick
    TestOpsJarstick
    Mar 16, 2020
    67
    个人觉得得看你得代码主要出路啥业务吧 ,比如你要写一个递归解析多层混合类型 json 数据,一般只有在 debug 的时候才会使用 type() 用得最多的还是 isinstance()
    siteshen
    siteshen
    Mar 16, 2020
    68
    @ManjusakaL
    1. 坚持用 python 2.x 的用户不是 type hint 的目标用户;
    2. type hint 如果是程序员主动发起的话,肯定是会配置一些基础的检查的;
    3. type hint 不是万能的,static analysis 比 no analysis 还是好了不少的,最不济还能当个注释,让 ide 能智能补全。
    siteshen
    siteshen
    Mar 16, 2020
    69
    @janxin 可能真的有这种最佳实践,毕竟动态类型语言的优势在于 duck type,即使要判断也应该是判断参数是否实现对应的接口,而不是要求参数是指定的类型。
    ManjusakaL
    ManjusakaL
    Mar 16, 2020 via Android
    70
    @siteshen yeap,但是我驳斥的是把 type hint 和防御式编程等价的
    pythonee
    pythonee
    Mar 16, 2020
    71
    这个问题每隔一段时间都会问自己吧,就好像选择红药丸和蓝药丸一样
    静态语言和动态语言的纠结,写静态语言总是让人更安心些
    wzwwzw
    wzwwzw
    Mar 16, 2020
    72
    在需要的时候写,在不需要的时候不写,如果你不知道这里是不是改写,那就是要写。isinstance 可能是更好的方式。或者使用 pydantic + mypy。
    Qzier
    Qzier
    Mar 16, 2020 via iPhone
    73
    具体看需求
    fhsan
    fhsan
    Mar 16, 2020
    74
    26.1. typing — Support for type hints
    janxin
    janxin
    Mar 16, 2020
    75
    @siteshen duck type 在类型标注里也有对应的啊...
    lewinlan
    lewinlan
    Mar 16, 2020 via Android
    76
    assert+isinstance,最标准用法。再考虑加函数参数和返回值类型
    hushao
    hushao
    Apr 9, 2020
    77
    即使需要判断也不建议 type,正确的应该用 isinstance
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2057 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 128ms · UTC 14:55 · PVG 22:55 · LAX 06:55 · JFK 09:55
    ♥ Do have faith in what you're doing.