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]。