Python 类型提示是在 PEP 484 中引入的,目的是为动态类型的语言带来静态类型的好处。虽然类型提示不会在运行时强制类型检查,但它们提供了一种指定变量、函数参数和返回值预期类型的方法,这些可以通过如 mypy
等静态分析工具来检查。这增强了代码的可读性,方便了调试,并提高了代码的整体可维护性。
类型提示在 Python 中使用注解来表示函数参数、返回值和变量赋值的类型。
Python 的类型提示可以用来指定各种类型的类型,如基本数据类型、集合、复杂类型以及用户自定义类型。typing
模块提供了许多内置类型来表示这些不同的类型:
让我们逐一详细地看看每一种类型。
基本数据类型
在 Python 中,当我们使用类型提示来指定基本类型时,可以直接使用类型的名称作为注解。
示例
下面是一个使用基本数据类型的示例:
from typing import Optional
def calculate_square_area(side_length: int) -> int:
return side_length ** 2
def calculate_circle_area(radius: float) -> float:
return 3.14 * radius * radius
def greet(name: str) -> str:
return f"Hello, {name}"
def is_adult(age: int) -> bool:
return age >= 18
def no_return_example() -> None:
print("This function does not return anything")
def safe_divide(x: int, y: Optional[int]) -> Optional[float]:
if y is None or y == 0:
return None
else:
return x / y
print(calculate_square_area(5))
print(calculate_circle_area(3.0))
print(greet("Alice"))
print(is_adult(22))
no_return_example()
print(safe_divide(10, 2))
print(safe_divide(10, 0))
print(safe_divide(10, None))
输出
执行上述代码我们将得到以下输出:
25
28.259999999999998
Hello, Alice
True
This function does not return anything
5.0
None
None
集合类型
在 Python 中,当我们处理列表、元组、字典等集合时,在类型提示中通常使用 typing
模块来指定集合类型。
示例
下面是使用集合类型的示例:
from typing import List, Tuple, Dict, Set, Iterable, Generator
def process_numbers(numbers: List[int]) -> List[int]:
return [num * 2 for num in numbers]
def coordinates() -> Tuple[float, float]:
return (3.0, 4.0)
def frequency_count(items: List[str]) -> Dict[str, int]:
freq = {}
for item in items:
freq[item] = freq.get(item, 0) + 1
return freq
def unique_characters(word: str) -> Set[str]:
return set(word)
def print_items(items: Iterable[int]) -> None:
for item in items:
print(item)
def squares(n: int) -> Generator[int, None, None]:
for i in range(n):
yield i * i
numbers = [1, 2, 3, 4, 5]
print(process_numbers(numbers))
print(coordinates())
items = ["apple", "banana", "apple", "orange"]
print(frequency_count(items))
word = "hello"
print(unique_characters(word))
print_items(range(5))
gen = squares(5)
print(list(gen))
输出
执行上述代码我们将得到以下输出:
[2, 4, 6, 8, 10]
(3.0, 4.0)
{'apple': 2, 'banana': 1, 'orange': 1}
{'l', 'e', 'h', 'o'}
0
1
2
3
4
[0, 1, 4, 9, 16]
可选类型
在 Python 中,可选类型用于指示一个变量可以是某个指定类型或者 None
。这对于函数可能不总是返回值或参数可以接受一个值或留空时特别有用。
示例
下面是一个使用可选类型的示例:
from typing import Optional
def divide(a: float, b: float) -> Optional[float]:
if b == 0:
return None
else:
return a / b
result1: Optional[float] = divide(10.0, 2.0)
result2: Optional[float] = divide(10.0, 0.0)
print(result1)
print(result2)
输出
执行上述代码我们将得到以下输出:
5.0
None
联合类型
Python 使用联合类型来允许一个变量接受不同类型的值。这对于函数或数据结构可以处理多种输入类型或产生不同类型输出的情况特别有用。
示例
下面是一个联合类型的示例:
from typing import Union
def square_root_or_none(number: Union[int, float]) -> Union[float, None]:
if number >= 0:
return number ** 0.5
else:
return None
result1: Union[float, None] = square_root_or_none(50)
result2: Union[float, None] = square_root_or_none(-50)
print(result1)
print(result2)
输出
执行上述代码我们将得到以下输出:
7.0710678118654755
None
任意类型
在 Python 中,任意类型 (Any
) 是一种特殊的类型提示,表示一个变量可以是任何类型。它基本上禁用了对该变量或表达式的类型检查。对于在事先不知道值的类型或处理动态数据时,这可能是有用的。
示例
下面是一个使用 Any
类型的示例:
from typing import Any
def print_value(value: Any) -> None:
print(value)
print_value(10)
print_value("hello")
print_value(True)
print_value([1, 2, 3])
print_value({'key': 'value'})
输出
执行上述代码我们将得到以下输出:
10
hello
True
[1, 2, 3]
{'key': 'value'}
类型别名
Python 中的类型别名用于给现有类型提供替代名称。它们可以通过给复杂的类型注解或类型组合提供清晰的名字来使代码更容易阅读。这对于处理嵌套结构或长类型提示特别有帮助。
示例
下面是一个使用类型别名的示例:
from typing import List, Tuple
Vector = List[int]
Coordinates = Tuple[float, float]
def scale_vector(vector: Vector, factor: float) -> Vector:
return [int(num * factor) for num in vector]
def calculate_distance(coord1: Coordinates, coord2: Coordinates) -> float:
x1, y1 = coord1
x2, y2 = coord2
return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
v: Vector = [1, 2, 3, 4]
scaled_v: Vector = scale_vector(v, 2.5)
print(scaled_v)
c1: Coordinates = (3.0, 4.0)
c2: Coordinates = (6.0, 8.0)
distance: float = calculate_distance(c1, c2)
print(distance)
输出
执行上述代码我们将得到以下输出:
[2, 5, 7, 10]
5.0
泛型
泛型类型创建能够处理任何类型的函数、类或数据结构,同时保持类型安全。typing
模块中的 TypeVar
和 Generic
构造使得这成为可能。它们对于制作能够处理各种类型而不影响类型检查的可复用组件特别有用。
示例
下面是一个泛型类型的示例:
from typing import TypeVar, List
T = TypeVar('T')
def first_element(items: List[T]) -> T:
return items[0]
int_list = [1, 2, 3, 4, 5]
str_list = ["apple", "banana", "cherry"]
first_int = first_element(int_list)
first_str = first_element(str_list)
print(first_int)
print(first_str)
输出
执行上述代码我们将得到以下输出:
1
apple
可调用类型
Python 中的 Callable
类型用于表明一个类型是函数或可调用对象。它位于 typing
模块中,并允许定义函数的参数类型和返回类型。这对于高阶函数特别有用。
示例
下面是一个使用 Callable
类型的示例:
from typing import Callable
def apply_operation(x: int, y: int, operation: Callable[[int, int], int]) -> int:
return operation(x, y)
def add(a: int, b: int) -> int:
return a + b
def multiply(a: int, b: int) -> int:
return a * b
result1 = apply_operation(5, 3, add)
result2 = apply_operation(5, 3, multiply)
print(result1)
print(result2)
输出
执行上述代码我们将得到以下输出:
8
15
文本类型
文本类型 (Literal
) 用于指定一个值必须精确地等于一组预定义值中的一个。
示例
下面是一个示例:
from typing import Literal
def move(direction: Literal["left", "right", "up", "down"]) -> None:
print(f"移动方向为 {direction}")
move("left")
move("up")
输出
执行上述代码我们将得到以下输出:
移动方向为 left
移动方向为 up
新类型
NewType
是 typing
模块中的一个函数,它允许我们创建从现有类型派生的独特类型。这对于我们通过区分相同底层类型的不同用途来增加代码的安全性是有用的。例如,我们可能希望区分用户ID和产品ID,尽管它们都表示为整数。
示例
下面是一个示例:
from typing import NewType
UserId = NewType('UserId', int)
ProductId = NewType('ProductId', int)
def get_user_name(user_id: UserId) -> str:
return f"ID 为 {user_id} 的用户"
def get_product_name(product_id: ProductId) -> str:
return f"ID 为 {product_id} 的产品"
user_id = UserId(42)
product_id = ProductId(101)
print(get_user_name(user_id))
print(get_product_name(product_id))
输出
执行上述代码我们将得到以下输出:
ID 为 42 的用户
ID 为 101 的产品