Python - 类型提示



Python 的类型提示在 PEP 484 中引入,旨在将静态类型的优势带入动态类型语言。虽然类型提示不会在运行时强制执行类型检查,但它们提供了一种指定变量、函数参数和返回值的预期类型的方法,这些类型可以通过静态分析工具(例如mypy)进行检查。这增强了代码的可读性,方便了调试,并提高了代码的整体可维护性。

Python 中的类型提示使用注解来指定函数参数、返回值和变量赋值。

Python 的类型提示可用于指定各种类型,例如基本数据类型、集合、复杂类型和自定义用户定义类型。typing 模块提供了许多内置类型来表示这些各种类型:

让我们逐一详细了解每一个。

基本数据类型

在 Python 中,当使用类型提示指定基本类型时,我们可以简单地使用类型的名称作为注解。

示例

以下是使用基本数据类型(例如整数、浮点数、字符串等)的示例:

from typing import Optional

# Integer type
def calculate_square_area(side_length: int) -> int:
   return side_length ** 2

# Float type
def calculate_circle_area(radius: float) -> float:
   return 3.14 * radius * radius

# String type
def greet(name: str) -> str:
   return f"Hello, {name}"

# Boolean type
def is_adult(age: int) -> bool:
   return age >= 18

# None type
def no_return_example() -> None:
   print("This function does not return anything")

# Optional type (Union of int or None)
def safe_divide(x: int, y: Optional[int]) -> Optional[float]:
   if y is None or y == 0:
      return None
   else:
      return x / y

# Example usage
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

# List of integers
def process_numbers(numbers: List[int]) -> List[int]:
   return [num * 2 for num in numbers]

# Tuple of floats
def coordinates() -> Tuple[float, float]:
   return (3.0, 4.0)

# Dictionary with string keys and integer values
def frequency_count(items: List[str]) -> Dict[str, int]:
   freq = {}
   for item in items:
      freq[item] = freq.get(item, 0) + 1
   return freq

# Set of unique characters in a string
def unique_characters(word: str) -> Set[str]:
   return set(word)

# Iterable of integers
def print_items(items: Iterable[int]) -> None:
   for item in items:
      print(item)

# Generator yielding squares of integers up to n
def squares(n: int) -> Generator[int, None, None]:
   for i in range(n):
      yield i * i

# Example usage
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)   # result1 will be 5.0
result2: Optional[float] = divide(10.0, 0.0)   # result2 will be None

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

Any 类型

在 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

# Define a type alias for a list of integers
Vector = List[int]

# Define a type alias for a tuple of coordinates
Coordinates = Tuple[float, float]

# Function using the type aliases
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

# Using the type aliases
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

# Define a type variable T
T = TypeVar('T')

# Generic function that returns the first element of a list
def first_element(items: List[T]) -> T:
   return items[0]

# Example usage
int_list = [1, 2, 3, 4, 5]
str_list = ["apple", "banana", "cherry"]

first_int = first_element(int_list)      # first_int will be of type int
first_str = first_element(str_list)      # first_str will be of type str

print(first_int)    
print(first_str)                                              

执行上述代码后,我们将得到以下输出

1
apple

可调用类型

Python 的Callable 类型用于表明某种类型是函数或可调用对象。它位于 typing 模块中,允许你定义函数的参数类型和返回类型。这对于高阶函数非常有用。

示例

以下是使用 Callable 类型进行类型提示的示例:

from typing import Callable

# Define a function that takes another function as an argument
def apply_operation(x: int, y: int, operation: Callable[[int, int], int]) -> int:
   return operation(x, y)

# Example functions to be passed as arguments
def add(a: int, b: int) -> int:
   return a + b

def multiply(a: int, b: int) -> int:
   return a * b

# Using the apply_operation function with different operations
result1 = apply_operation(5, 3, add)        # result1 will be 8
result2 = apply_operation(5, 3, multiply)   # result2 will be 15

print(result1)  
print(result2)                                                

执行上述代码后,我们将得到以下输出

8
15

字面量类型

Literal 类型用于指定值必须是预定义值集合中的一个。

示例

以下是一个示例:

from typing import Literal

def move(direction: Literal["left", "right", "up", "down"]) -> None:
   print(f"Moving {direction}")

move("left")  # Valid
move("up")    # Valid                                     

执行上述代码后,我们将得到以下输出

Moving left
Moving up

NewType

NewType 是 typing 模块中的一个函数,它允许我们创建从现有类型派生的 distinct 类型。这对于通过区分相同底层类型的不同用途来增强代码类型安全性非常有用。例如,我们可能希望区分用户 ID 和产品 ID,即使两者都表示为整数。

示例

以下是一个示例:

from typing import NewType

# Create new types
UserId = NewType('UserId', int)
ProductId = NewType('ProductId', int)

# Define functions that use the new types
def get_user_name(user_id: UserId) -> str:
   return f"User with ID {user_id}"

def get_product_name(product_id: ProductId) -> str:
   return f"Product with ID {product_id}"

# Example usage
user_id = UserId(42)
product_id = ProductId(101)

print(get_user_name(user_id))   # Output: User with ID 42
print(get_product_name(product_id))  # Output: Product with ID 101                                   

执行上述代码后,我们将得到以下输出

User with ID 42
Product with ID 101
广告
© . All rights reserved.