这篇文章实际是The Ultimate Guide to Python Type Checking文的导读和个人理解,有不当之处,以原文为准。内容分为四个部分:
- 类型注解和提示(Type annotations and type hints)
- 代码里添加静态类型
- 静态类型检查
- 运行时强制类型一致
Hello Type!
动态类型
任何语言都有类型系统,Python也不例外。Python的类型和一般的动态语言一样,运行时检查和变量类型可以发生改变
当一个int类型和str相加时会抛出运行错误,但是如果不运行这段代码,Python便不会报错。
>>> 1 + "two" # Now this is type checked, and a TypeError is raised
TypeError: unsupported operand type(s) for +: 'int' and 'str'
同一个变量可以有不同的类型
>>> thing = "Hello"
>>> type(thing)
<class 'str'>
>>> thing = 28.1
>>> type(thing)
<class 'float'>
静态类型
与动态类型相反,静态类型检查可以不需要程序运行,在编译阶段就可以发现类型错误,例如Java和C语言。
String thing;
thing = "Hello";
此时thing这个变量已经确定为String类型,便不可再发生变化,并且thing也不能赋值为其他类型。
Python的抉择
虽然Python在PEP 3107(https://www.python.org/dev/peps/pep-3107/)第一次引入了函数注解,可以在函数中标记变量类型,并在PEP 484(https://www.python.org/dev/peps/pep-0484/)中由Guido(Python创始人)等继续引入类型提示,但是Python会一直是动态语言(https://www.python.org/dev/peps/pep-0484/#non-goals),类型不会影响Python的实际运行。
既然Python引入了静态类型系统,有什么影响呢?
先谈优点:
- 方便记录代码,生成相应的文档。
- 改善IDE和linters,藉由类型检查可以帮助开发者发现类型错误。
- 最重要的在于大型项目可以获得更好、更干净的架构,减少开发者的失误。
作为动态语言引入类型检查,自然不会只有好处。
- 类型的加入需要花费开发者更多的时间
- 类型提示只适合于Python3.X以上,函数注解适用于3.X和2.7,并不能向后兼容
- 如果使用typing(https://docs.python.org/3/library/typing.html)包,本来就慢的Python就更慢了。
作为一个对开发者友好的编程语言,Python也支持渐进式的给项目加入类型系统(https://www.python.org/dev/peps/pep-0483/)。接下来更深入的了解Python类型系统
如何使用类型系统
从一个简单的代码开始:
def headline(text, align=True):
if align:
return f"{text.title()}\n{'-' * len(text)}"
else:
return f" {text.title()} ".center(50, "o")
运行如下:
>>> print(headline("python type checking"))
Python Type Checking
--------------------
>>> print(headline("python type checking", align=False))
oooooooooooooo Python Type Checking oooooooooooooo
补充上类型注解:
def headline(text: str, align: bool = True) -> str:
...
这时text: str表示text这个变量应该是str类型,同样的align是bool类型,二headline函数返回的结果为str类型。当然此时违反给定的类型传入,这段代码也是可以运行的:
>>> print(headline("python type checking", align="left"))
Python Type Checking
--------------------
Python里支持类型检查的主要是Mypy包(Python的类型体系也来源于这个博士项目),除此之外还有谷歌的pytype(https://github.com/google/pytype)和Facebook的Pyre(https://pyre-check.org/)。本文主要介绍mypy包的使用。将上述代码改写进headline.py文件中:
# headlines.py
2
3 def headline(text: str, align: bool = True) -> str:
4 if align:
5 return f"{text.title()}\n{'-' * len(text)}"
6 else:
7 return f" {text.title()} ".center(50, "o")
8
9 print(headline("python type checking"))
10 print(headline("use mypy", align="center"))
运行:
$ mypy headlines.py
headlines.py:10: error: Argument "align" to "headline" has incompatible
type "str"; expected "bool"
此时mypy会报错在第十行类型错误,此时将print(headline("use mypy", align="center"))改成print(headline("use mypy", align=True))运行便会正常。
$ mypy headlines.py
$
运行时检查
虽说Python永远不会改变其动态语言本质,但是依然有一些包支持运行时类型错误便会报错,例如Enforce(https://pypi.org/project/enforce/), Pydantic(https://pypi.org/project/pydantic/),或者是Pytypes(https://pypi.org/project/pytypes/)。毕竟所有的类型都会存储在annotations中。
结尾
Python的类型系统介绍就到此结束了,作为Python3引入的新特性,让Python在大型项目中更加游刃有余。
进群:960410445 即可获取书十套PDF!