惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

爱范儿
爱范儿
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
G
GRAHAM CLULEY
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V2EX - 技术
V2EX - 技术
The Last Watchdog
The Last Watchdog
S
Secure Thoughts
Webroot Blog
Webroot Blog
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
H
Heimdal Security Blog
H
Help Net Security
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
The GitHub Blog
The GitHub Blog
Jina AI
Jina AI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
F
Full Disclosure
小众软件
小众软件
S
Securelist
罗磊的独立博客
NISL@THU
NISL@THU
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cisco Blogs
云风的 BLOG
云风的 BLOG
C
CERT Recently Published Vulnerability Notes
Cisco Talos Blog
Cisco Talos Blog
Know Your Adversary
Know Your Adversary
S
Schneier on Security
D
DataBreaches.Net
M
MIT News - Artificial intelligence
V
Vulnerabilities – Threatpost
N
News and Events Feed by Topic
有赞技术团队
有赞技术团队
F
Fortinet All Blogs
T
Tenable Blog
The Register - Security
The Register - Security
C
Check Point Blog
AWS News Blog
AWS News Blog
Cloudbric
Cloudbric
C
CXSECURITY Database RSS Feed - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google Online Security Blog
Google Online Security Blog
博客园 - 叶小钗
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 司徒正美

博客园 - 悠哉大斌

AI Agent 安全沙箱技术对比:E2B、Cube Sandbox 与 Docker Sandboxes linux 升级 claude code的坑 debian(WSL) apt 代理配置 linux内核之Namespaces、Cgroups、Capabilities、Seccomp和Landlock 大语言模型推理中的隐藏瓶颈及其解决方法 Docker Sandboxes 技术是什么,和docker容器有什么区别 什么是 Docker Agent以及一个Docker Agent示例 windows wsl 安装 Temurin® JDK claude Code 和 codex 作为编程代理,前者使用typescript开发,后者使用rust,他们的决策依据是什么 Java 并发编程发展史与 java.util.concurrent 全景解析 LLM 真的改变了编码风格吗? 如果人工智能会犯错且不精确,为什么它正在改变世界? Python 的协程模型和 JavaScript 的 async/await python闭包和function.__closure__特殊属性 python 的 dunder name和 sunder name 基于nodejs设计REST API的知名开源框架 windows上使用node-oracledb Thick 模式连接 Oracle 11g Claude Code CLI连接 DeepSeek V4模型后调用报400错误 python里对象(object)到底是什么 Python 泛型演变史 Python 类型别名的演变 Python 类型提示的演变史 Alibaba AgentScope 和 microsoft agent framework 详细对比分析 spring AI Alibaba Agent Framework 和 agentscope有什么区别和联系 AI Agent协作模式以及主流开源框架对协作模式的支持 Tailscale 是如何接管 DNS 的? Agent = Model + Harness 使用rust编写typescript编译器的难点在什么地方,哪些数据结构是rust不擅长的? TypeScript/JavaScript 中的异步迭代语句 js中的生成器函数 Tailscale Serve and Funnel openclaw gateway的网络绑定模式 websocket协议和http协议有何依赖关系? MCP通信的双方是谁? claude code MCP 安装范围 如何在wsl2环境下给claude code cli 配置 playwright-mcp wsl的网络模式有哪几种,有哪些区别? AI Agent memory是什么? ai agent skills是什么? Go测试生态系统工具与最佳实践深度调研(聚焦认证授权系统) 线性代数中常见矩阵类型的概念关系思维导图 三种主流授权策略
PEP 593 新增的Annotated 类型
悠哉大斌 · 2026-04-22 · via 博客园 - 悠哉大斌

PEP 593 引入的 Annotated(在 typing 模块中)主要作用是:

一句话理解

给类型附加额外的元数据(metadata),同时不改变原有类型语义。

它的形式是:

from typing import Annotated

x: Annotated[int, metadata]

这里:

  • int 是真实类型(静态类型检查器仍认为它是 int
  • metadata 是附加信息,供框架、库、运行时工具使用。

为什么需要它?

以前:

类型提示只负责:

age: int

只能表达“这是 int”。

但现实中经常需要表达:

  • 这个 int 必须大于 0
  • 这个字符串是邮箱
  • 这个参数来自 HTTP Header
  • 这个字段数据库里是主键

单靠类型系统无法表达。

Annotated 就是把这些信息塞进去:

from typing import Annotated

age: Annotated[int, "must be positive"]

主要作用


1. 给类型加约束(Validation)

常见于 Pydantic

from typing import Annotated
from pydantic import BaseModel, Field

class User(BaseModel):
    age: Annotated[int, Field(gt=0, lt=150)]

这里:

int

还是类型;

Field(gt=0)

是元数据。

作用:

  • 类型检查仍认为是 int
  • Pydantic 用 metadata 做运行时验证

2. 给框架提供额外语义

比如 FastAPI:

from typing import Annotated
from fastapi import Header

async def endpoint(
    token: Annotated[str, Header()]
):
    ...

str 是类型。

Header() 表示:

这个参数来自 HTTP Header。

非常优雅。


3. 自定义元数据(领域标记)

from typing import Annotated

UserId = Annotated[int, "primary key"]

id: UserId = 42

你可以附加业务语义。

甚至:

class Range:
    def __init__(self, min_, max_):
        self.min = min_
        self.max = max_

Score = Annotated[int, Range(0, 100)]

4. 让静态类型系统和运行时工具解耦

这是 PEP 593 的核心设计思想。

类型检查器:

Annotated[int, xxx]

默认等价于:

int

元数据不会破坏类型系统。

而运行时工具可读取:

from typing import get_type_hints

print(get_type_hints(obj, include_extras=True))

可以拿到:

Annotated[int, ...]

和普通 type hint 区别

普通:

name: str

只有类型。


Annotated:

name: Annotated[str, MaxLen(20)]

类型 + 元数据。


本质像:

类型本身 + 注释插件

PEP 593 出现前怎么做?

以前常这样:

from pydantic import Field

age: int = Field(gt=0)

约束和默认值混在一起。

PEP 593 后更干净:

age: Annotated[int, Field(gt=0)]

类型和元数据分离。


可以叠:

from typing import Annotated

x: Annotated[
    int,
    "positive",
    "database index",
]

多个框架可以各取所需。


实际最经典例子

FastAPI 参数声明

from typing import Annotated
from fastapi import Query

async def search(
    q: Annotated[str, Query(min_length=3)]
):
    ...

相当于:

  • 类型是 str
  • 参数来自 query string
  • 最小长度 3

全放在一个声明里。


类型检查怎么看?

from typing import Annotated

x: Annotated[int, "foo"]

y: int = x   # 没问题

像 mypy 通常把它当 int


它不是做什么的?

不是新类型:

Annotated[int, ...]

不是 PositiveInt 这种新类型。

只是给 int 加说明。


类比理解

像数据库:

age INT

只是类型。

而:

age INT CHECK(age > 0)

类型 + 元信息/约束。

Annotated 很像这个。


PEP 593 设计目标(官方总结)

主要是为:

  1. 类型之外携带 metadata
  2. 支持框架扩展
  3. 不影响静态类型检查

什么时候该用?

适合:

  • FastAPI 参数声明
  • Pydantic v2
  • ORM 字段描述
  • 自定义验证系统
  • 类型驱动元编程

不适合:

只是普通变量注释时没必要:

x: int

够了。


一个现代 Python 风格示例(推荐写法)

from typing import Annotated
from pydantic import BaseModel, Field

PositiveInt = Annotated[int, Field(gt=0)]

class Product(BaseModel):
    price: PositiveInt

非常常见。