介绍
在本文中,将了解 Python 类型检查 (Type-Checking) 。
在本教程中,将了解以下内容:
- 类型注释和类型提示
- 将静态类型添加到代码中,包括你的代码和其他人的代码
- 运行静态类型检查器
- 在运行时强制类型
视频介绍如下:
Python 类型提示和静态类型检查
类型系统
所有编程语言都包含某种类型系统,该系统形式化了它可以使用哪些类别的对象以及如何处理这些类别。
例如,一个类型系统可以定义一个数字类型,42作为一个数字类型对象的例子。
动态类型 (Dynamic Typing)
Python 是一种动态类型语言。这意味着 Python 解释器仅在代码运行时进行类型检查,并且允许变量的类型在其生命周期内更改。以下虚拟示例演示 Python 具有动态类型:
>>> if False:
... 1 + "two" # This line never runs, so no TypeError is raised
... else:
... 1 + 2
...
3
>>> 1 + "two" # Now this is type checked, and a TypeError is raised
TypeError: unsupported operand type(s) for +: 'int' and 'str'
在第一个示例中,分支1 + "two"
从不运行,因此从不检查类型。
第二个示例显示,当1 + "two"
被评估时,它会引发一个 TypeError ,因为在Python中整数和字符串不能相加。
接下来,让我们看看变量是否可以改变类型:
>>> thing = "Hello"
>>> type(thing)
<class 'str'>
>>> thing = 28.1
>>> type(thing)
<class 'float'>
type()
返回对象的类型。
这些例子证实了事物的类型是允许更改的,Python在类型更改时正确地推断出它的类型。
静态类型 (Static Typing)
与动态类型相反的是静态类型。静态类型检查在不运行程序的情况下执行。在大多数静态类型语言中,例如C和Java,这是在编译程序时完成的。
对于静态类型,通常不允许变量更改类型,尽管可能存在将变量强制转换为其他类型的机制。
让我们来看一个来自静态类型语言的快速示例。下面的 Java 片段:
String thing;
thing = "Hello";
第一行声明变量名thing
在编译时绑定到字符串类型。这个名字永远不可能换成另一种类型。在第二行,事物被赋值。它永远不能被分配一个不是字符串对象的值。例如,如果后来说 thing=28.1f
,编译器会因为不兼容的类型而引发错误。
Python将始终是一种动态类型的语言。然而,PEP 484引入了类型提示,这使得也可以对Python代码进行静态类型检查。
与大多数其他静态类型语言中的类型工作方式不同,类型提示本身不会导致 Python 强制执行类型。正如名字所说,类型提示只是建议类型。还有其他一些工具,将在后面看到,它们使用类型提示执行静态类型检查。
鸭子类型 (duck typing)
在谈论Python时经常使用的另一个术语是鸭子类型。
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
鸭子类型是一个与动态类型相关的概念,其中对象的类型或类不如它定义的方法重要。使用鸭子类型根本不需要检查类型,而是检查给定方法或属性是否存在。
例如,可以在任何定义了 .__len__()
方法的 Python 对象上调用 len()
:
>>> class TheHobbit:
def __len__(self):
return 95022
>>> the_hobbit = TheHobbit()
>>> len(the_hobbit)
95022
请注意,对 len()
的调用给出了 .__len__()
方法的返回值。 其实len()
的实现本质上等价于以下:
def len(obj):
return obj.__len__()
为了调用 len(obj),对 obj 的唯一真正约束是它必须定义一个 .__len__()
方法。
否则,对象的类型可以与 str、list、dict 或 TheHobbit 等不同。
在使用结构子类型对 Python 代码进行静态类型检查时,一定程度上支持 Duck 类型。 稍后您将了解有关鸭子类型的更多信息。
Hello Types
在本节中,将看到如何向函数添加类型提示。
下面的函数通过添加适当的大写字母和装饰线将文本字符串转换为标题: