如何定义可接受类型参数的Python类?关于type hints的疑问
嘿,我来帮你把这两个问题掰明白!
一、Type Hints的正式语言规范
Python 3.5引入的类型提示(Type Hints)并不是凭空设计的,它的核心依据是PEP 484——这是Python官方关于类型提示的正式规范文档,后续还有PEP 483(类型系统的理论基础)、PEP 526(变量注解语法)等补充规范,这些PEPs共同定义了类型提示的语法、语义和使用场景。
你提到的Union[int, str],按照规范来说,它表示一个变量的类型可以是int或者str。不过要注意:Python本身是动态类型语言,类型提示只是静态检查工具(比如mypy、pyright)的依据,运行时Python并不会强制检查变量类型是否符合注解——也就是说,你哪怕给标注了Union[int, str]的变量赋值一个float,Python运行时也不会报错,只有静态检查工具会提示你类型不匹配。
二、如何定义可接受类型参数的Python类(泛型类)
要写能接受类型参数的类,也就是泛型类,我们可以借助typing模块里的Generic基类(Python 3.9+也支持直接用标准容器的泛型写法,不过自定义泛型类还是得用Generic)。下面给你举几个实用例子:
基础泛型类示例
from typing import Generic, TypeVar # 先定义一个类型变量,用TypeVar声明,T是业内约定俗成的命名 T = TypeVar('T') class Box(Generic[T]): def __init__(self, content: T) -> None: self.content = content def get_content(self) -> T: return self.content # 实例化时明确指定类型参数 int_box = Box[int](123) print(int_box.get_content()) # 静态检查工具会识别返回值为int类型 str_box = Box[str]("hello") print(str_box.get_content()) # 静态检查工具会识别返回值为str类型
多类型参数的泛型类
如果你的类需要多个类型参数,也可以声明多个TypeVar:
from typing import Generic, TypeVar K = TypeVar('K') V = TypeVar('V') class KeyValuePair(Generic[K, V]): def __init__(self, key: K, value: V) -> None: self.key = key self.value = value def get_pair(self) -> tuple[K, V]: return (self.key, self.value) # 实例化时指定两个类型参数 pair = KeyValuePair[str, int]("age", 25)
Python 3.9+的简化写法
从Python 3.9开始,标准库的容器类型(比如list、dict)已经支持直接作为泛型使用,不需要再从typing里导入List、Dict了。自定义泛型类的写法和之前一致,只是类型注解里的容器可以更简洁:
# Python 3.9+ 专属写法 from typing import Generic, TypeVar T = TypeVar('T') class Stack(Generic[T]): def __init__(self) -> None: self.items: list[T] = [] # 直接用list[T]代替旧写法List[T] def push(self, item: T) -> None: self.items.append(item) def pop(self) -> T: return self.items.pop()
简单来说,泛型类的核心就是用TypeVar定义类型变量,然后让类继承Generic[类型变量],这样就能在类的属性、方法里复用这个类型参数,让静态检查工具能精准推断出不同实例的具体类型。
内容的提问来源于stack exchange,提问作者Peter Bašista

