Type Hints 初步了解
import collections from ctypes import Array from decimal import Decimal from fractions import Fraction from typing import Optional, Union, TypeAlias, NewType, Any, NoReturn, List, NamedTuple, Callable, Literal, TypeVar, \ Hashable, Tuple, TypeVarTuple, Generic, Protocol, Iterable, TypedDict, NotRequired, Required def func1(a: Union[int, str], b: Optional[str] = None) -> None: # Optional 是形参为[str],使用默认值None的情况下使用 ... # ----------------------------------------------------------------- Hexadecimal: TypeAlias = str | int # 类型别名的定义 def func2(a: Hexadecimal) -> None: # 标注新的类型别名 ... UserID = NewType("UserID", int) # 派生后在形参上标注,实参就只能使用UserID类型的参数,而不能使用int类型 # ----------------------------------------------------------------- def func3(a: UserID) -> None: # 标注新的类型 ... # func3(124) # 类型检查错误 func3(UserID(123214)) userid = UserID(123) func3(userid) PassWord = NewType("PassWord", UserID) # 依然可以在NewType类型上进行继续派生 # 派生的类型并不是真正的类无法用于class,却是个真的类型,与类型别名不一样 # 若指定使用NewType的子类型则无法使用父类型 # ----------------------------------------------------------------- def func4(a: Any) -> NoReturn: # Any类型代表任意类型,如 int,str,float,list,dict,tuple甚至pd.Series # 在形参中任何未标注的类型都是Any型 ... # NoReturn表示一个函数从不返回 # ----------------------------------------------------------------- def func5(text: str) -> List[str] | list[str] | collections.deque[int | str] | dict[str, int]: # -> list[str] 表示是一个容器类型出除List/list之外还有tuple等 # dict 中标注的是dict[KeyType, ValueType] return text.split() # ----------------------------------------------------------------- def func6(a: tuple[str, float, str]) -> float: # 在tuple的情况下可以使用该形式 ... # ----------------------------------------------------------------- class Coordinate(NamedTuple): latitude: float longitude: float def func7(a: Coordinate): # 在类继承之后,子类可以表示父类,比如Coordinate[float, float]可以表示tuple[float, float],但是反过来不行 ... # ----------------------------------------------------------------- # ... 可以用作表示长度 # tuple[int, ...] # 表示int类型构成的元组 # tuple[int] # 表示只有一个int值的元组 # 如果省略方括号,tuple等价于tuple[Any, ...]而非tuple[Any] # ----------------------------------------------------------------- class Order: pass def func8(a: Optional[Callable[["Order"], float]] = None, /) -> None: # 在形参中 / 表示在/前的参数只能通过位置来指定 # 在形参中 * 表示在*后面的参数只能通过关键字指定 ... Fruit = Literal["apple", "banana", "orange"] # Literal表示这能是里面的3个字面量,也就是说在Fruit中只能是apple,banana,orange三个字面量之一 # ----------------------------------------------------------------- T = TypeVar("T") # 泛型 NumberT = TypeVar("NumberT", float, Decimal, Fraction) # 限定泛型 HashableT = TypeVar("HashableT", bound=Hashable) # 有界泛型 ColorRGB: TypeAlias = Tuple[int, int, int] HexiDecimal: TypeAlias = Union[int, str] # ----------------------------------------------------------------- # def func9(a: Array[Time, Batch, Height, Width, Channels]): # ... # ----------------------------------------------------------------- Dtype = TypeVar("Dtype") Shape = TypeVarTuple("Shape") # TypeVarTuple # 泛型元组 class ArrayT(Generic[Dtype, Shape]): def __abs__(self) -> Array[Dtype, *Shape]: ... def __add__(self, other: Array[Dtype, *Shape]) -> Array[Dtype, *Shape]: ... Height = NewType("Height", int) Weight = NewType("Weight", int) x: ArrayT[float, Height, Weight] = ArrayT() x_2: ArrayT[float, Literal[300], Literal[400]] = ArrayT() # ----------------------------------------------------------------- class SupportsLessThan(Protocol): def __lt__(self, other: Any) -> bool: ... # sort排序就是调用lt方法进行排序的 # 需要进行自定义协议需要用到Protocol LT = TypeVar("LT", bound=SupportsLessThan) # 也就是说传入的对象是可以进行sort的对象 def top(series: Iterable[LT], length: int) -> list[LT]: ordered = sorted(series, reverse=False) return ordered[:length] # ----------------------------------------------------------------- class BookDict(TypedDict): # NamedTuple实际上是一个dataclass,会创建一个类 # TypedDict 不是类,不会创建dataclass # 在不使用静态类型检查器时,TypedDict和注释没有任何区别,也不会起到任何作用,它唯一的作用就是提高代码的可读性,而dataclass则会在运行时创建一个真实的类,这与TypedDict有明显的不同。 isbn: str title: Required[str] # 表示是必选的 authors: list[str] pagecount: NotRequired[int] # NotRequired 表示该参数是可选的 def to_xml(book: BookDict) -> str: ... def from_json(data: str) -> BookDict: ... # ----------------------------------------------------------------- # 在导入模块时,Python实际上会记录模块中的type hints,它们会被保存在__annotations__属性 # from clip_annot import clip # print(clip.__annotations__) # {'text': <class 'str'>, 'max_len': <class 'int'>, 'return': <class 'str'>} # ----------------------------------------------------------------- # Type Hints中除了支持泛型参数以外还支持泛型类 TClass = TypeVar("TClass") class Node(Generic[TClass]): def __init__(self, data: T, next: Optional['Node[T]']): ... @property def data(self) -> T: ... @property def next(self) -> 'Node[T]': ... # 需要注意的是,这里的Generic[T]需要在最后继承。如果这里的Node类继承了其他父类,那么需要将其他继承放在前面。 # 在自定义泛型类后,就可以使用Node[...]这样的语法为自定义的泛型类绑定类型了,例如Node[int]、Node[str]。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)