Python的显式类型版本?
我挺喜欢Python的语法糖和标准库函数。
不过,有一个我不太喜欢的地方,就是隐式类型。
有没有一种Python版本可以使用显式类型,同时还能和比如PyPi上的包兼容呢?
[我在考虑RPython]
5 个回答
现在是2021年,有一个叫做 Deal 的库,它不仅提供了一个强大的静态类型检查工具,还允许你指定一些条件,比如在代码运行前后的要求、循环中的不变条件,明确说明对异常和输入输出/副作用的期望,甚至可以正式证明代码的正确性(虽然这只适用于Python的一小部分)。
下面是他们GitHub上的一个例子:
# the result is always non-negative
@deal.post(lambda result: result >= 0)
# the function has no side-effects
@deal.pure
def count(items: List[str], item: str) -> int:
return items.count(item)
# generate test function
test_count = deal.cases(count)
现在我们可以:
- 运行
python3 -m deal lint
或者 flake8 来静态检查错误。 - 运行
python3 -m deal test
或者 pytest 来生成和运行测试。 - 直接在项目中使用这个函数,并在运行时检查错误。
不,你不能既想要蛋糕又想吃蛋糕。
Python 很棒,因为它是动态类型的!就这样。(这也是它有那么好用的标准库的原因)
静态类型语言只有两个优点:1)速度 - 当算法一开始就正确时,2)编译错误。
关于第一个优点:
- 使用 PyPi,
- 进行性能分析,
- 使用 ctype 库来获得更好的性能。
通常只有 10% 或更少的代码是性能关键的。那剩下的 90% 呢?尽情享受动态类型的好处吧。
关于第二个优点:
- 使用类(和契约),
- 进行单元测试,
- 进行重构,
- 使用好的代码编辑器。
通常数据并不适合标准数据类型,因为这些类型对存储内容的要求太严格或太宽松。确保你自己验证数据。
单元测试是算法测试的必备工具,没有编译器能为你做到这一点,它应该能捕捉到由于错误数据类型引起的任何问题(而且与编译器不同,它们可以细致到你需要的程度)。
重构可以解决当你不确定某些修改是否会破坏代码时的问题(同样,强类型数据也不能保证这一点)。
而好的代码编辑器可以解决很多问题……试试 Sublime Text 一段时间。然后你就会明白我在说什么。
(要明确,我并没有给你想要的答案,而是质疑你的需求,特别是那些你没有在问题中提到的。)
简单来说,答案是否定的。你所问的这个问题是Python语言的基本特性,想要改变它就得大幅度改动语言,这样就不再是Python了。
我猜测你可能不喜欢在重新赋值时变量的类型会被重新定义?如果这是你代码中的一个问题,你可以考虑其他方法来检查这个情况。
从Python 3开始,Python标准中引入了类型注解的功能,这个改动是根据PEP 3107的提议。
到了Python 3.5,PEP 0484在此基础上进一步发展,引入了类型提示,并且增加了一个叫做typing
的模块,这样你就可以为变量或函数的返回值指定类型了。
from typing import Iterator
def fib(n: int) -> Iterator[int]:
a, b = 0, 1
while a < n:
yield a
a, b = b, a + b
上面的例子来自https://pawelmhm.github.io
根据484的说明:
虽然这些注解在运行时可以通过常规的 __annotations__属性访问,但运行时并不会进行类型检查。相反,这个提议假设存在一个独立的离线类型检查器,用户可以自愿在他们的源代码上运行它。基本上,这样的类型检查器就像一个非常强大的代码检查工具。 (当然,个别用户可以在运行时使用类似的检查器来执行设计契约或即时优化,但这些工具目前还不够成熟。)
总结
虽然Python提供了这种“静态类型”的形式,但在运行时并不会强制执行,Python解释器会忽略你提供的任何类型说明,仍然会使用鸭子类型来推断类型。因此,找到一个能够检测类型问题的代码检查工具就完全靠你自己了。
进一步说明
将类型引入Python标准的动机主要受到mypy的影响,所以你可以考虑去了解一下它们。它们还提供了一些示例,可能会对你有帮助。