Python Typing:提升代码可读性

PythonPythonBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本教程中,你将学习如何使用 Python 的 typing 模块为代码添加类型提示。类型提示通过明确指示函数的预期输入和输出类型,有助于使代码更具可读性和可维护性。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/DataStructuresGroup(["Data Structures"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python/BasicConceptsGroup -.-> python/variables_data_types("Variables and Data Types") python/BasicConceptsGroup -.-> python/numeric_types("Numeric Types") python/BasicConceptsGroup -.-> python/type_conversion("Type Conversion") python/DataStructuresGroup -.-> python/lists("Lists") python/DataStructuresGroup -.-> python/tuples("Tuples") python/DataStructuresGroup -.-> python/dictionaries("Dictionaries") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/arguments_return("Arguments and Return Values") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") subgraph Lab Skills python/variables_data_types -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/numeric_types -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/type_conversion -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/lists -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/tuples -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/dictionaries -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/function_definition -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/arguments_return -.-> lab-7848{{"Python Typing:提升代码可读性"}} python/classes_objects -.-> lab-7848{{"Python Typing:提升代码可读性"}} end

基本类型

类型提示是 Python 3.5 引入的一项特性,而 typing 模块则在 Python 3.5.2 中被添加,用于提供一组标准的类型注解。从 typing 模块中导入相关类型以开始使用类型提示。

from typing import List, Tuple, Dict

基本类型的类型提示非常简单,只需使用类型本身作为提示即可。

在终端中输入以下命令以打开 Python shell。

python3
  1. 定义一个类型为 int 的变量,为其赋值并打印。
age: int = 25
print(age) ## 输出:25
  1. 定义一个类型为 float 的变量,为其赋值并打印。
temperature: float = 98.6
print(temperature) ## 输出:98.6
  1. 定义一个类型为 bool 的变量,为其赋值并打印。
is_raining: bool = True
print(is_raining) ## 输出:True
  1. 定义一个类型为 str 的变量,为其赋值并打印。
def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet("Alice")) ## 输出:Hello, Alice!
  1. 定义一个函数,该函数接受两个类型为 int 的参数,将它们相乘并返回结果,结果类型为 int
def multiply(x: int, y: int) -> int:
    return x * y

result = multiply(5, 10)
print(result) ## 输出:50

容器与泛型

对于容器类型(如列表、字典和集合)的类型提示,可以使用泛型来更具体地指定类型。

提示:序号为 1-3 的实验可以在 Python shell 中实现,而序号为 4 的实验需要在 WebIDE 中实现。

  1. 定义一个类型为 List[int] 的变量,为其赋值并打印。
from typing import List
numbers: List[int] = [1, 2, 3, 4, 5]
print(numbers) ## 输出:[1, 2, 3, 4, 5]
  1. 定义一个类型为 Dict[str, int] 的变量,为其赋值并打印。
from typing import Dict
ages: Dict[str, int] = {"Alice": 25, "Bob": 30, "Charlie": 35}
print(ages) ## 输出:{'Alice': 25, 'Bob': 30, 'Charlie': 35}
  1. 定义一个类型为 Tuple[str, int, float] 的变量,为其赋值并打印。
from typing import Tuple
person: Tuple[str, int, float] = ("Alice", 25, 5.7)
print(person) ## 输出:('Alice', 25, 5.7)
  1. 定义一个函数,该函数接受一个整数列表作为参数,并返回一个新的整数集合。

在 WebIDE 中创建一个名为 list_to_set.py 的项目,并输入以下内容。

from typing import List, Set

def get_unique_elements(elements: List[int]) -> Set[int]:
    return set(elements)

numbers = [1, 2, 2, 3, 4, 4, 4, 5]
unique_numbers = get_unique_elements(numbers)
print(unique_numbers)  ## 输出:{1, 2, 3, 4, 5}

使用以下命令运行脚本。

python list_to_set.py

自定义类型

你也可以使用自定义类型和类作为类型提示。

提示:本实验在 WebIDE 中实现。

  1. 定义一个 Person 类,其属性 nameage 分别具有类型提示 strint,并定义一个方法 get_summary,返回一个总结人物姓名和年龄的字符串。

在 WebIDE 中创建一个名为 str_and_int_to_str.py 的项目,并输入以下内容。

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
    def get_summary(self) -> str:
        return f"{self.name} is {self.age} years old."

person1 = Person("Alice", 25)
print(person1.get_summary()) ## 输出:Alice is 25 years old.

使用以下命令运行脚本。

python str_and_int_to_str.py
  1. 定义一个 Point 类,其属性 xy 均为 float 类型,并定义一个方法 distance,该方法接受另一个点作为参数并返回两点之间的距离。

在 WebIDE 中创建一个名为 other_to_float.py 的项目,并输入以下内容。

import math

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y
    def distance(self, other: "Point") -> float:
        return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)

point1 = Point(0, 0)
point2 = Point(3, 4)
print(point1.distance(point2)) ## 输出:5.0

使用以下命令运行脚本。

python other_to_float.py

类型别名

类型别名可以创建更具可读性的类型提示,尤其是对于复杂类型。

在 WebIDE 中创建一个名为 type_aliases.py 的项目,并输入以下内容。

from typing import List, Tuple

Coordinate = Tuple[float, float]
Path = List[Coordinate]

def get_distance(coord1: Coordinate, coord2: Coordinate) -> float:
    return ((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)**0.5

start = (0, 0)
end = (3, 4)
print(get_distance(start, end))  ## 输出:5.0

使用以下命令运行脚本。

python type_aliases.py

Optional 与 None

当值可以是特定类型或 None 时,可以使用 Optional 类型。

  1. 定义一个函数,该函数接受一个可选的 int 类型参数,如果参数不是 None,则将其乘以 2,并返回结果;如果输入为 None,则返回 None

在 WebIDE 中创建一个名为 option_and_none_1.py 的项目,并输入以下内容。

from typing import Optional

def double_or_none(number: Optional[int]) -> Optional[int]:
    if number is not None:
        return number * 2
    else:
        return None

result1 = double_or_none(5)
result2 = double_or_none(None)
print(result1, result2) ## 输出:10 None

使用以下命令运行脚本。

python option_and_none_1.py
  1. 定义一个 Person 类,其属性 address 可以是有效的地址字符串或 None

在 WebIDE 中创建一个名为 option_and_none_2.py 的项目,并输入以下内容。

from typing import Optional

class Person:
    def __init__(self, name: str, age: int, address: Optional[str]):
        self.name = name
        self.age = age
        self.address = address

person1 = Person("Alice", 25, "123 Main St")
person2 = Person("Bob", 30, None)
print(person1.name, person1.age, person1.address) ## 输出:Alice 25 123 Main St
print(person2.name, person2.age, person2.address) ## 输出:Bob 30 None

使用以下命令运行脚本。

python option_and_none_2.py

Callable

Callable 类型用于指定函数或方法的类型。

在 WebIDE 中创建一个名为 callable.py 的项目,并输入以下内容。

from typing import Callable

def apply_function(value: int, func: Callable[[int], int]) -> int:
    return func(value)

def double(x: int) -> int:
    return x * 2

print(apply_function(5, double))  ## 输出:10

使用以下命令运行脚本。

python callable.py

TypedDict

TypedDict 允许你创建具有特定键和值类型的自定义字典。

提示:TypedDict 在 Python 3.8 中引入,因此你需要运行 Python 3.8 或更高版本来使用它。

以下是一个示例:

在 WebIDE 中创建一个名为 typeddict.py 的项目,并输入以下内容。

from typing import TypedDict

class PersonInfo(TypedDict):
    name: str
    age: int

def greet(person: PersonInfo) -> str:
    return f"Hello, {person['name']}! You are {person['age']} years old."

alice_info: PersonInfo = {"name": "Alice", "age": 30}
print(greet(alice_info))  ## 输出:Hello, Alice! You are 30 years old.

使用以下命令运行脚本。

python typeddict.py

NewType

NewType 是 Python 中 typing 模块提供的一种类型提示,它允许你创建一个新类型,该类型只是对现有类型的包装。这可以为变量和函数参数添加更多的语义意义。

以下是一个示例:

在 WebIDE 中创建一个名为 newtype.py 的项目,并输入以下内容。

然后执行以下 Python 脚本。

from typing import NewType

UserId = NewType("UserId", int)
OrderId = NewType("OrderId", int)

def get_order(order_id: OrderId) -> str:
    return f"Order with ID: {order_id}"

order_id = OrderId(123)
user_id = UserId(123)

print(get_order(order_id))  ## 输出:Order with ID: 123

使用以下命令运行脚本。

python newtype.py

静态类型检查

在 Python 中,可以使用类型提示和静态类型检查工具(如 mypy)进行静态类型检查。类型提示用于指示变量、函数参数和返回值的预期类型。以下是一个示例:

首先,安装 mypy

pip install mypy

以下是一个示例:

在 WebIDE 中创建一个名为 mypy.py 的项目,并输入以下内容。

def add_numbers(x: int, y: int) -> int:
    return x + y

result = add_numbers(2, 3)
print(result)

然后对你的脚本运行 mypy

mypy mypy.py

这将为你提供代码中发现的任何类型不一致的反馈。

总结

就是这样!你现在已经知道如何使用 Python 的 typing 模块为代码添加类型提示了。类型提示可以显著提高代码的可读性和可维护性,使处理更大的代码库和与他人协作变得更加容易。