avatar

刘刚刚的blog

采菊东篱下,悠然见南山🦥

  • 首页
  • 大模型应用
  • 常用软件/工具
  • Halo
  • 关于
Home Typing
文章

Typing

Posted 20 days ago Updated 20 days ago
By Administrator
23~29 min read


类型注释让python 有了更好的编辑器提示功能。

基础使用

对函数参数和返回值,进行类型注释

def surface_area_of_cube(edge_length: float) -> str:
    return f"The surface area of the cube is {6 * edge_length ** 2}."

类型别名

类型别名适用于简化复杂的类型签名

type Vector = list[float]
# 为了向下兼容,也可以使用以下方式
# Vector = list[float]
​
def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]
​
# 通过类型检查;浮点数列表是合格的 Vector。
new_vector = scale(2.0, [1.0, -4.2, 5.4])

NewType

静态类型检查器把新类型当作原始类型的子类,这种方式适用于捕捉逻辑错误。

不允许继承NewType的产生的类型

from typing import NewType
​
UserId = NewType('UserId', int)
def get_user_name(user_id: UserId) -> str:
    pass
​
# 通过类型检查
user_a = get_user_name(UserId(42351))
​
​
# 'output' 的类型为 'int' 而非 'UserId'
output = UserId(23413) + UserId(54341)

Callable

Callable[[int], str] 使用两个值:参数列表和返回类型

# 接受两个Callable的参数
def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    ...  # 函数体
​
# ...表示接受任意形参列表
x: Callable[..., str]
x = str     # 可以
x = concat  # 同样可以

泛型

表示容器元素的预期类型

from collections.abc import Mapping, Sequence
​
class Employee: ...
​
# Sequence[Employee] 表明该序列中的所有元素
# 都必须是 "Employee" 的实例。
# Mapping[str, str] 表明该映射中的所有键和所有值
# 都必须是字符串。
def notify_by_email(employees: Sequence[Employee],
                    overrides: Mapping[str, str]) -> None: ...
​
​

类型行参化:

from collections.abc import Sequence
​
def first[T](l: Sequence[T]) -> T:  # 函数是 TypeVar "T" 泛型
    return l[0]
​
​

TypeVar

from collections.abc import Sequence
from typing import TypeVar
​
U = TypeVar('U')                  # 声明类型变量 "U"
​
def second(l: Sequence[U]) -> U:  # 函数是 TypeVar "U" 泛型
    return l[1]

Sequence与List的区别:Sequence是一个抽象基类,许多具体的类型(如 list、tuple、str 等)都属于 Sequence。

Mapping与dict的区别:Mapping表示函数可以接受任何支持键值对访问的类型,如 collections.defaultdict 或自定义的映射类型

标注元组

元组的标注与其他的类型不同。

# 第 1 个元素是个整数,第 2 个元素是个字符串
y: tuple[int, str] = (5, "foo")
​
# 错误: 类型标注表明是长度为 1 的元组,
# 但 ``z`` 却被赋值为长度为 3 的元组
z: tuple[int] = (1, 2, 3)
​
​
​
# 所有元素都是相同类型的 T,需要使用 tuple[T, ...]
x: tuple[int, ...] = (1, 2)
​
# ``y`` 只能被赋值为一个空元组
y: tuple[()] = ()

类对象的类型

可以通过对象获取其对应的类型:type(c)

type 的合法形参包括:类, Any, 类型变量 以及前面这些类型的并集。

type[Any] 等价于 type,它是 Python 的 元类层级结构 的根对象。

a = 3         # 为 ``int`` 类型
b = int       # 为 ``type[int]`` 类型
c = type(a)   # 同样为 ``type[int]`` 类型
​
​
class User: ...
class ProUser(User): ...
class TeamUser(User): ...
​
def make_new_user(user_class: type[User]) -> User:
    # ...
    return user_class()
​
make_new_user(User)      # 可以
make_new_user(ProUser)   # 同样可以: ``type[ProUser]`` 是 ``type[User]`` 的子类型
make_new_user(TeamUser)  # 仍然可以
make_new_user(User())    # 错误: 预期为 ``type[User]`` 但得到 ``User``
​
​
def new_non_team_user(user_class: type[BasicUser | ProUser]): ...
​
new_non_team_user(BasicUser)  # 可以
new_non_team_user(ProUser)    # 可以

标注生成器和协程

生成器使用:Generator[YieldType, SendType, ReturnType]

异步生成器使用:AsyncGenerator[YieldType, SendType],不支持ReturnType

当SendType, ReturnType不设置时,默认为None

def echo_round() -> Generator[int, float, str]:
    sent = yield 0
    while sent >= 0:
        sent = yield round(sent)
    return 'Done'
  
# 异步
async def infinite_stream(start: int) -> AsyncGenerator[int]:
    while True:
        yield start
        start = await increment(start)

一些简单的迭代器,可以使用Iterable[YieldType]或 Iterator[YieldType]

异步:AsyncIterable[YieldType] 和 AsyncIterator[YieldType]

def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1
​
# 异步        
async def infinite_stream(start: int) -> AsyncIterator[int]:
    while True:
        yield start
        start = await increment(start)        

协程:

from collections.abc import Coroutine
c: Coroutine[list[str], str, int]  # 在其他地方定义的协程
x = c.send('hi')                   # 推断 'x' 的类型为 list[str]
async def bar() -> None:
    y = await c                    # 推断 'y' 的类型为 int

用户定义的泛型类型

围绕单个 类型变量 T 实现参数化的。 这也使得 T 成为类体内部有效的类型。

​
from logging import Logger
​
class LoggedVar[T]:
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value
        
# 为了与 python3.11 兼容,也可以使用Generic
from typing import TypeVar, Generic
​
T = TypeVar('T')
​
class LoggedVar(Generic[T]):
​

typing.Union

Union[X, Y] 等价于 X | Y ,意味着满足 X 或 Y 之一。

Optional[X] 等价于 X | None (或 Union[X, None] ) 。

  • 联合类型之联合类型会被展平,例如:

    Union[Union[int, str], float] == Union[int, str, float]
  • 单参数之联合类型就是该参数自身,例如:

    Union[int] == int  # 该构造器确实返回 int
  • 冗余的参数会被跳过,例如:

    Union[int, str, int] == Union[int, str] == int | str
  • 比较联合类型,不涉及参数顺序,例如:

    Union[int, str] == Union[str, int]
  • 不可创建 Union 的子类或实例。

  • 没有 Union[X][Y] 这种写法。

python
License:  CC BY 4.0
Share

Further Reading

Apr 21, 2025

Typing

类型注释让python 有了更好的编辑器提示功能。 基础使用 对函数参数和返回值,进行类型注释 def surface_area_of_cube(edge_length: float) -> str:    return f"The surface area of the cube is {6 *

Feb 25, 2025

python多进程多线程下的计数及日志打印

注意点: 需要保证在多进程内的进程锁是同一个 需要保证在单进程中的多线程内线程锁是同一个 # logger.py import multiprocessing import threading ​ ​ class Logger_test:    def __init__(self, process

Dec 25, 2022

python-迭代器、生成器、协程

迭代器 Python中当容器对象提供了对迭代的支持时,可以通过container.__iter__()来返回一个迭代器对象。 迭代器需要支持以下两个方法,这两个方法共同构成了迭代器协议: iterator.__iter__() 该方法返回迭代器本身,这个方法是配合for和in使用所必须的。 iter

OLDER

大模型返回中json_schema与json_mode的区别

NEWER

dify 并发配置优化

Recently Updated

  • 文本切分-语义分割(Semantic Chunking)
  • dify 并发配置优化
  • Typing
  • 大模型返回中json_schema与json_mode的区别
  • Async

Trending Tags

Halo 运维 postgresql 设计模式 linux就该这么学 nas rag odoo python 文本切分

Contents

©2025 刘刚刚的blog. Some rights reserved.

Using the Halo theme Chirpy