Python type hints được giới thiệu trong PEP 484 để mang lại lợi ích của kiểu tĩnh cho một ngôn ngữ kiểu động. Mặc dù các gợi ý kiểu không thực thi kiểm tra kiểu tại thời gian chạy, chúng cung cấp một cách để chỉ định các kiểu mong đợi của variables , tham số hàm và giá trị trả về, có thể được kiểm tra bởi các công cụ phân tích tĩnh như mypy . Điều này nâng cao khả năng đọc mã, tạo điều kiện thuận lợi cho việc gỡ lỗi và cải thiện tính bảo trì tổng thể của mã.
Type hints trong Python sử dụng chú thích cho các tham số hàm, giá trị trả về và gán biến.
Python's type hints có thể được sử dụng để chỉ định nhiều loại khác nhau như data types cơ bản, bộ sưu tập, các loại phức tạp và các loại do người dùng định nghĩa. Mô-đun typing cung cấp nhiều loại tích hợp sẵn để đại diện cho các loại khác nhau này −
Hãy xem từng cái một, lần lượt và chi tiết.
Trong Python, khi sử dụng type hints để chỉ định các kiểu cơ bản, chúng ta có thể đơn giản sử dụng tên của kiểu đó làm chú thích.
Dưới đây là ví dụ về việc sử dụng các kiểu dữ liệu cơ bản như số nguyên, số thực, chuỗi, v.v. −
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))
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
25 28.259999999999998 Hello, Alice True This function does not return anything 5.0 None None
Trong Python, khi làm việc với các tập hợp như lists , tuples , dictionaries , v.v. trong type hints , chúng ta thường sử dụng mô-đun typing để chỉ định các loại tập hợp.
Dưới đây là ví dụ về Collections được sử dụng trong type hints −
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))
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
[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]
Trong Python, Optional types được sử dụng để chỉ ra rằng một biến có thể thuộc một kiểu nhất định hoặc là None. Điều này đặc biệt hữu ích khi một hàm có thể không luôn trả về giá trị hoặc khi một tham số có thể chấp nhận một giá trị hoặc có thể để không xác định.
Dưới đây là ví dụ về việc sử dụng optional types trong type hints −
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)
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
5.0 None
Python sử dụng kiểu Union để cho phép một biến chấp nhận các giá trị của các kiểu khác nhau. Điều này rất hữu ích khi một hàm hoặc cấu trúc dữ liệu có thể làm việc với nhiều loại đầu vào khác nhau hoặc sản xuất các loại đầu ra khác nhau.
Dưới đây là ví dụ về điều này −
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)
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
7.0710678118654755 None
Trong Python, Any type là một kiểu gợi ý đặc biệt cho biết rằng một biến có thể thuộc bất kỳ kiểu nào. Nó về cơ bản vô hiệu hóa việc kiểm tra kiểu cho biến hoặc biểu thức đó. Điều này có thể hữu ích trong các tình huống mà kiểu của một giá trị không được biết trước hoặc khi làm việc với dữ liệu động.
Sau đây là ví dụ về việc sử dụng loại Any trong Type hint −
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'})
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
10 hello True [1, 2, 3] {'key': 'value'}
Type aliases trong Python được sử dụng để cung cấp các tên thay thế cho các kiểu đã tồn tại. Chúng có thể làm cho mã dễ đọc hơn bằng cách cung cấp các tên rõ ràng cho các chú thích kiểu phức tạp hoặc sự kết hợp của các kiểu. Điều này đặc biệt hữu ích khi làm việc với các cấu trúc lồng nhau hoặc các gợi ý kiểu dài.
Dưới đây là ví dụ về việc sử dụng Type Aliases trong Type hints −
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)
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
[2, 5, 7, 10] 5.0
Generic types Tạo các hàm, lớp hoặc cấu trúc dữ liệu có thể xử lý bất kỳ loại nào trong khi vẫn duy trì tính an toàn kiểu. Các cấu trúc TypeVar và Generic trong mô-đun typing làm cho điều này trở nên khả thi. Chúng hữu ích cho việc tạo các thành phần tái sử dụng có thể hoạt động với các loại khác nhau mà không làm giảm kiểm tra kiểu.
Dưới đây là ví dụ về nó −
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)
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
1 apple
Kiểu Callable của Python được sử dụng để chỉ ra rằng một kiểu là một hàm hoặc một đối tượng có thể gọi được. Nó có trong mô-đun typing và cho phép bạn định nghĩa các kiểu của các tham số và kiểu trả về của một hàm. Điều này rất hữu ích cho các hàm bậc cao.
Dưới đây là ví dụ về việc sử dụng kiểu Callable trong type hint −
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)
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
8 15
Loại Literal được sử dụng để chỉ định rằng một giá trị phải chính xác là một trong số các giá trị đã được định nghĩa trước.
Dưới đây là ví dụ −
from typing import Literal def move(direction: Literal["left", "right", "up", "down"]) -> None: print(f"Moving {direction}") move("left") # Valid move("up") # Valid
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
Moving left Moving up
NewType là một hàm trong mô-đun typing cho phép chúng ta tạo ra các kiểu riêng biệt được kế thừa từ các kiểu hiện có. Điều này có thể hữu ích để thêm tính an toàn cho kiểu dữ liệu trong mã của chúng ta bằng cách phân biệt giữa các cách sử dụng khác nhau của cùng một kiểu dữ liệu cơ bản. Ví dụ, chúng ta có thể muốn phân biệt giữa ID người dùng và ID sản phẩm mặc dù cả hai đều được biểu diễn dưới dạng số nguyên.
Dưới đây là ví dụ −
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
Khi thực thi đoạn mã trên, chúng ta sẽ nhận được output −
User with ID 42 Product with ID 101