大家是如何实时检查 Python 变量类型的? - V2EX
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
szzhiyang
V2EX    Python

大家是如何实时检查 Python 变量类型的?

  •  
  •   szzhiyang 2019-09-20 17:17:01 +08:00 5722 次点击
    这是一个创建于 2212 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我目前使用的 Python 实时类型检查方案是在 Microsoft Python Extension for VS Code 中启用 mypy --strict 检查,但是发现这个方案存在一些瑕疵,比如将鼠标悬停在某个变量名上方时 VS Code 不能详细提示它的类型(它只会把 Dict[str, int] 类型提示为 dict 类型)。

    我还尝试过 PyCharm ,不过不知道是因为 PyCharm 本身做不到还是我没找对门路,我一直没能将它设置为实时使用 mypy 检查。

    我现在想知道:

    • 大家是如何实时检查 Python 变量类型的?

    • Python 的类型检查体验真的没法达到 C++、C#、TypeScript 那样的程度吗?




    回复前必读:

    • 我想要的是 边写边检查,而不是在执行代码前才检查
    • 我了解 Python 的 Type Hints 语法( PEP 484 和 PEP 526 )
    • 不要回复“我不做类型检查”或者“没必要做类型检查”的言论

    第 1 条附言    2019-09-21 17:58:49 +08:00

    如果你不理解为何要做类型检查,请观看该视频:

    Carl Meyer - Type-checked Python in the real world - PyCon 2018


    44 条回复    2019-09-28 09:21:24 +08:00
    expkzb
        1
    expkzb  
       2019-09-20 17:27:01 +08:00   1
    变量名加类型后缀
    szzhiyang
        2
    szzhiyang  
    OP
       2019-09-20 17:27:58 +08:00
    我承诺向认真回帖的热心 V 友发送感谢!
    star00
        3
    star00  
       2019-09-20 17:29:12 +08:00
    换语言
    shintendo
        4
    shintendo  
       2019-09-20 17:30:06 +08:00   1
    匈牙利命名法!
    szzhiyang
        5
    szzhiyang  
    OP
       2019-09-20 17:31:28 +08:00
    @expkzb 我知道这个语法,我在帖子中说了。
    szzhiyang
        6
    szzhiyang  
    OP
       2019-09-20 17:33:03 +08:00
    @shintendo 那该怎么命名类型为 Dict[str, Set[int]] 的变量呢?
    ClericPy
        7
    ClericPy  
       2019-09-20 17:36:34 +08:00   1
    Pydantic for the data parts.

    fastapi 里看到这个, 感觉还行, vscode 里开个 mypy 凑合用
    szzhiyang
        8
    szzhiyang  
    OP
       2019-09-20 17:39:50 +08:00
    @ClericPy 多谢,不过这个并不是我想要的那种,我想要的是一套 Linting 工具链。
    janxin
        9
    janxin  
       2019-09-20 17:42:14 +08:00
    个看起来只是插件的问题,不过我试了一下我的插件的提示是正常的?
    ClericPy
        10
    ClericPy  
       2019-09-20 17:43:51 +08:00
    @szzhiyang 知道啊... 但是靠谱的试过都一般般啊, 之前最顺手是 pyright, 后来还是改回 mypy 了
    szzhiyang
        11
    szzhiyang  
    OP
       2019-09-20 17:44:25 +08:00
    @janxin 请问你用的是什么编辑器的什么插件?它能提示 Dict[str, Set[int]] 这种复杂的类型吗?
    szzhiyang
        12
    szzhiyang  
    OP
       2019-09-20 17:46:21 +08:00
    @ClericPy 谢谢你,我也试过 Pyright,不过它最严格的 Linting 规则达不到我的要求。
    iyaozhen
        13
    iyaozhen  
       2019-09-20 17:46:56 +08:00 via Android
    对楼主需求场景不太了解。

    日常开发中也有类型检查的需求,不过仅仅是方便对象方法提示,一般是通过注释显式表明类型。因为 pycharm 的类型推导确实不太准
    SbloodyS
        14
    SbloodyS  
       2019-09-20 17:50:05 +08:00
    我用 typing....
    ClericPy
        15
    ClericPy  
       2019-09-20 17:51:23 +08:00
    @szzhiyang 哈哈... 你能试的都试过了, 所以最好去 Reddit 上问... Pydantic 解决的是在 linter 里友好的显示类型, 你要的反而是个 linter... Pycharm 已经够高级了, 要啥自行车
    pakro888
        16
    pakro888  
       2019-09-20 18:16:14 +08:00 via Android
    使用 pycharm 按住 ctrl 同时指针悬浮到变量上可以提示吧。
    janxin
        17
    janxin  
       2019-09-20 18:29:53 +08:00
    跟你一样的插件,启用了 LSP。不过我只是看了一下同文件的,不同文件的没试过,理论上应该也差不多
    szzhiyang
        18
    szzhiyang  
    OP
       2019-09-20 18:33:52 +08:00
    @janxin LSP 是啥?
    szzhiyang
        19
    szzhiyang  
    OP
       2019-09-20 18:37:06 +08:00
    @ClericPy

    很多非常明显的类型错误 PyCharm 都查不出来,比如下列代码:

    test_str: str = "Hello World"
    test_int: int = 123456
    test_str += test_int

    是因为我没设置好 PyCharm 吗?
    clino
        20
    clino  
       2019-09-20 18:44:48 +08:00 via Android
    检查当然用 isinstance 啦
    szzhiyang
        21
    szzhiyang  
    OP
       2019-09-20 21:42:34 +08:00
    @clino 你理解错我的意思了。
    LokiSharp
        22
    LokiSharp  
       2019-09-20 21:44:37 +08:00
    @szzhiyang #19 要用 mypy
    lance6716
        23
    lance6716  
       2019-09-20 21:59:53 +08:00 via Android
    这种 pyobject 强行检查类型又有多大用途呢…不如理清楚写码思路
    szzhiyang
        24
    szzhiyang  
    OP
       2019-09-20 22:07:26 +08:00
    @lance6716 这么做的好处会随着项目规模的增长变得越发明显。
    lance6716
        25
    lance6716  
       2019-09-20 22:09:33 +08:00 via Android
    @szzhiyang 那就不如换静态类型语言算了
    szzhiyang
        26
    szzhiyang  
    OP
       2019-09-20 22:11:02 +08:00
    @lance6716 要是能换,我就不会发这个帖子了。
    ClericPy
        27
    ClericPy  
       2019-09-20 22:18:40 +08:00
    @szzhiyang 不知道了, Pycharm 尝试过 5 次迁移都放弃了... 现在常驻 vscode 的...


    szzhiyang
        28
    szzhiyang  
    OP
       2019-09-20 22:29:34 +08:00
    @ClericPy 之前我一直以为用 PyCharm 写 Python 的体验就像用 Visual Studio 写 C# 那样,后来亲自尝试 PyCharm 后才发现我太天真了。
    szzhiyang
        29
    szzhiyang  
    OP
       2019-09-20 22:35:41 +08:00
    @pakro888 但是没有 mypy 加成的 PyCharm 对变量类型的检查能力非常羸弱。
    ClericPy
        30
    ClericPy  
       2019-09-20 22:38:59 +08:00
    @szzhiyang 我用过 Pycharm, 比你说的强太多了... 肯定也有插件什么的吧, 那么复杂一东西, 内存比 vscode 还少... 挺厉害了, 还是不会用
    yegle
        31
    /div> yegle  
       2019-09-21 03:53:46 +08:00
    Python 的类型检查当然是垃圾啊。你来写一个类型注解,参数类型支持 iterable of strings 但是 exclude str type。
    ila
        32
    ila  
       2019-09-21 08:05:36 +08:00 via Android
    @expkzb 手动滑稽,me too
    a719114136
        33
    a719114136  
       2019-09-21 11:26:19 +08:00
    为啥要检查,又不能带来性能提升。 至于减少 bug,我写 py 这么久还真没见过因为这个造成的 bug (这种类型的 bug 在早期测试的时候完全能发现)。
    最多也就是函数的参数,返回值用 Type Hints 给个类型提示,函数里面那想咋用就咋用呗
    szzhiyang
        34
    szzhiyang  
    OP
       2019-09-21 12:59:45 +08:00 via iPhone
    @a719114136 类型检查还是很有必要的,不然 TypeScript 就不会问世了。
    szzhiyang
        35
    szzhiyang  
    OP
       2019-09-21 13:04:12 +08:00
    @ila 如果变量的数据类型比较复杂的话,比如 Dict[str, Set[int]],那就很难起变量名了。
    billlee
        36
    billlee  
       2019-09-21 15:23:15 +08:00
    弃坑上车 java
    bakabie
        37
    bakabie  
       2019-09-21 22:50:55 +08:00
    弃坑上 Go (
    sazima
        38
    sazima  
       2019-09-22 07:53:45 +08:00
    目前我也有点迷, 一般都是这么写
    user: User = session.query(User).first()
    users: Sequence[User] = session.query(User).all()

    def get_user_by_id(use_id: int) -> User:
    ....
    laike9m
        39
    laike9m  
       2019-09-22 10:26:32 +08:00   1
    试试 Google 的 pytype 呢?
    laike9m
        40
    laike9m  
       2019-09-22 10:45:57 +08:00
    @yegle 的确是个问题。没有 char 就算了这个不好改,但是我觉得 typing 应该加入 exclude types 支持。
    laike9m
        41
    laike9m  
       2019-09-22 11:04:01 +08:00
    @yegle 我又想了一下,根源不是不支持 exclude,而是不支持 AND 条件。但是 typing 支持 Union,所以按照现在的设计应该写成 Union[List[str], Tuple[str], Set[str]]。从某种意义上说这样更明确。
    szzhiyang
        42
    szzhiyang  
    OP
       2019-09-22 12:12:05 +08:00
    @laike9m 多谢,不过 pytype 好像不能被配置成实时检查的效果。
    yegle
        43
    yegle  
       2019-09-28 03:28:07 +08:00
    @laike9m 确实需要 exclude,或者正式支持 typing.Char

    举个例子,你给的 Union 类型并不支持 typing.Iterable,不支持 typing.KeysView/typing.ItemsView/typing.ValuesView


    这个是我几年前提的 FR:github.com/python/typing/issues/510
    laike9m
        44
    laike9m  
       2019-09-28 09:21:24 +08:00
    @yegle 是的。我的意思其实就是 typing 现在的思路是白名单。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2618 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 15:19 PVG 23:19 LAX 08:19 JFK 11:19
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86