Python 静态类型检查不再引发副作用:TYPE_CHECKING 的最佳实践解析
引言
在 Python 3.5 引入的 typing
模块极大改善了 Python 的类型提示能力,使得 IDE 的智能提示和静态类型检查成为可能。然而在实际开发中,类型标注可能会带来一些意想不到的副作用。
类型标注的价值与痛点
当我们在参数或返回值中添加类型标注时,IDE 能够基于这些信息提供精准的代码补全。例如:


可以看到,当我添加了类型标注后,pycharm 可以自动提示我们 A
类有一个 aa
属性。
那如果 A
类在另一个模块中呢?

仍然可以正常提示我们 A
类拥有哪些属性,现在到这里还没有问题。并且这种方式可以很方便我们后续的编码,不用再一个一个属性的敲上去了,也防止属性敲错了 Python 不会提示我们而导致的 bug。
但是静态检查没有问题,我们运行起来试试呢?


我们发现问题了,那就是 test1
中的代码被执行了。现在的问题是,我并不想将 Demo1
类导入进来, 只是想使用 Demo1
类来进行类型标注,以方便编码。
目前的类型检查的确做到了可以帮助我们来自动补全,但是会带来一些副作用,副作用有几点:
可能导致预料之外的初始化代码执行
可能在复杂项目中互相导入导致循环引用
导入过多的类仅用于类型标注导致的性能问题
虽然以上的问题可以通过其他方法来解决,但是解决起来成本比较高。
TYPE_CHECKING
现在我们可以通过 typing
模块的 TYPE_CHECKING
(Python 3.5.2+)常量来解决这个问题,先看官方文档:

它是在 Python 3.5.2 引入的一个常量,这个常量在静态类型检查的时候会被设置为 True
,但是在运行时会被设置为 False
。
有什么用呢?我们可以在导入 Demo1
类的时候加一个判断,如果这个常量为 True
的话,则认为是在进行静态类型检查,静态类型检查会通过,不会报错。在实际运行的时候,常量的值会被设置为 False
,也就不会实际导入 Demo1
这个类,从而避免了可能的循环导入、无效 import
导致的性能问题和预料外的初始化代码执行。
这里有一个需要注意的点,那就是第一次使用的时候要把类型使用单引号引起来。
来看效果:


已经可以正常导入了,并且也不会导致初始化代码执行,说明没有实际导入 test1
这个模块。
总结
使用这种方法,可以在写代码时实现自动补全,并且防止意外 bug,避免循环导入和无效 import
的问题,从而提高我们的开发效率。
本文章首发于个人博客 LLLibra146's blog
本文作者:LLLibra146
更多文章请关注公众号 (LLLibra146):
![]()
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!
版权声明: 本文为 InfoQ 作者【LLLibra146】的原创文章。
原文链接:【http://xie.infoq.cn/article/6f262b199c4e30f0880dc917f】。未经作者许可,禁止转载。
评论