简单聊聊Python的类型系统

编译自https://realpython.com/python-type-checking/

这篇文章实际是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在大型项目中更加游刃有余。

相关的学习可以参考: https://github.com/Bogdanp/cursive_re/blob/master/cursive_re/exprs.py 一个很好的学习如何使用类型提示的材料 https://www.bernat.tech/the-state-of-type-hints-in-python/ 更深入的理解类型提示

原文发布于微信公众号 - 鸿的学习笔记(shujuxuexizhilu)

原文发表时间:2019-01-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券