python typing

Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

Type Hints

from typing import ....     是Python 中用于类型提示(Type Hints)的常用导入语句。它们帮助开发者和工具(如 IDE、mypy 等)理解变量、函数参数和返回值的预期类型,提高代码可读性和健壮性。

在构建AI系统(MCP,agent)时, 正确的类型提示可以更好让LLM调用MCP和agent工具

List

表示一个可读写的列表(list),可以指定列表中元素的类型。

List[元素类型]
from typing import List


arr: List[int] = [1, 2, 3]
print(arr[0])
arr[0] = 5  # 在读写 list[T] 类型时不会出现任何错误提示


def get_names() -> List[str]:
    return ["Alice", "Bob", "Charlie"]

def add_numbers(nums: List[int]) -> int:
    return sum(nums)


print(get_names())
print(add_numbers(arr))

⚠️ 注意:从 Python 3.9 开始,可以直接使用内置的 list 类型进行泛型标注(如 list[str]),不再强制需要 typing.List。但在旧版本(<3.9)或为了兼容性,仍常用 List

Sequence

表示一个只读的任何序列类型,包括 listtuplestrrange 等(只要是实现了 __getitem__ 和 __len__ 的有序容器,所以在写Sequence[T]类型时会提示 not define __setitem__)。

适用于“只读”或“不需要修改”的场景。

Sequence[元素类型]
from typing import Sequence


arr: Sequence[str] = ["a", "b", "c"]
arr[0] = "d"  # 代码可以正常运行,但编译器提示: Class 'Sequence' does not define '__setitem__', so the '[]' operator cannot be used on its instances
print(arr)  # ["d", "b", "c"]


def print_items(items: Sequence[str]) -> None:
    for item in items:
        print(item)

# 合法
print_items(["a", "b", "c"])    # list
print_items(("a", "b", "c"))    # tuple
print_items("hello world")      # 字符串本身就是容器类型
# 不合法
print_items([1, 2, 3])  # 代码可以正常运行,但编译器会提示: Expected type 'Sequence[str]', got 'list[int]' instead

✅ 建议:如果你的函数只遍历或读取数据,不修改容器,优先使用 Sequence 而不是 List,这样更灵活。

Optional

表示某个值可以是某种类型,也可以是 None

等价于 Union[T, None]

Optional[类型]
from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    # 假设根据 ID 查找用户名,找不到返回 None
    users = {1: "Alice", 2: "Bob"}
    return users.get(user_id)  # 可能返回 str 或 None

name: Optional[str] = find_user(3)
if name is not None:
    print(f"Found: {name}")


def get_hobby(user_id: int) -> Optional[Sequence[str]]:
    users = {1: ["a", "b"], 2: ["a", "b"]}
    return users.get(user_id)

hobby: Optional[Sequence[str]] = get_hobby(3)
if hobby is not None:
    print(f"Found: {hobby}")

✅ 使用场景:函数可能失败、字典查找、可选配置参数等。

📌 提示:Python 3.10+ 还支持更简洁的写法,例如 str | None 代替 Optional[str],但 Optional 仍然广泛使用且清晰。

Any

Any 表示任意类型。使用 Any 相当于“关闭”类型检查——它告诉类型检查器(如 mypy、PyCharm 等):“这个值可以是任何东西,不要报错”。

⚠️ 虽然方便,但应尽量避免滥用 Any,因为它会削弱类型系统的安全性。

使用场景

  • 与动态数据交互(如 JSON 解析结果)
  • 临时占位(待后续完善类型)
  • 与未提供类型注解的第三方库交互
from typing import Any

def log_value(value: Any) -> None:
    print(f"Value: {value}, type: {type(value)}")

log_value(42)          # int
log_value("hello")     # str
log_value([1, 2, 3])   # list

Dict

表示一个可读写的字典,指定键和值的类型

Dict[KeyType, ValueType]

📌 从 Python 3.9+ 开始,也可以直接用内置的 dict 进行泛型标注(如 dict[str, int]),但 typing.Dict 在旧版本中仍广泛使用。

from typing import Dict


config: Dict[str, str] = {
    "host": "localhost",
    "port": "8080"  # 注意:这里值是 str,不是 int
}


def get_user_info() -> Dict[str, str]:
    return {"name": "a", "age": "23"}

user_info: Dict[str, str] = get_user_info()

Dict 表示可变字典,如果只需要读取,也可以考虑用 Mapping(更通用,类似 Sequence vs List)。

TypedDict

TypedDict 用于定义具有固定键名和特定值类型的字典结构,特别适合表示 JSON 数据、配置对象、API 响应等。

与普通 Dict 不同,TypedDict 的每个键都有明确的名称和类型,支持 IDE 自动补全和类型检查。

from typing import TypedDict

class Person(TypedDict):
    name: str
    age: int
    email: str

# 使用
p: Person = {
    "name": "Alice",
    "age": 30,
    "email": "alice@example.com"
}

默认情况下,TypedDict 要求所有字段都必须存在(total=True)。如果某些字段是可选的,可以设置 total=False

class Movie(TypedDict, total=False):
    title: str
    year: int
    director: str  # 可选

# 合法
m1: Movie = {"title": "Inception"}
m2: Movie = {"title": "Interstellar", "year": 2014, "director": "Nolan"}

案例

from typing import TypedDict, List

class ApiResponse(TypedDict):
    status: str
    data: List[Person]

response: ApiResponse = {
    "status": "success",
    "data": [
        {"name": "Bob", "age": 25, "email": "bob@example.com"}
    ]
}

Literal

Literal用于限制变量或参数只能取某些特定的字面量值(literal values),比如固定的字符串、数字、布尔值等

from typing import Literal

var: Literal["red", "green", "blue"] = "red"

注意事项

  1. 值必须是字面量(literal):只能是 strbytesintboolenum 成员,或 None

    # ❌ 错误:变量不能作为 Literal 参数
    mode = "read"
    x: Literal[mode]  # 报错!
  2. 大小写敏感

    Literal["Read"] != Literal["read"]
  3. 不要过度使用:如果选项很多或动态变化,考虑用 Enum 或运行时验证。

🎯 一句话记住:当你想说“这个参数只能是这几个固定值之一”时,就用 Literal

常见使用场景

1. 限制函数参数为特定选项(替代枚举或字符串常量)

from typing import Literal

def set_mode(mode: Literal["read", "write", "append"]) -> None:
    if mode == "read":
        print("Reading file...")
    elif mode == "write":
        print("Writing file...")
    elif mode == "append":
        print("Appending to file...")

# 合法调用
set_mode("read")

# 类型检查器会报错 ❌
# set_mode("delete")  # 错误:'delete' 不在允许的字面量中

💡 这比写 mode: str 更安全,避免拼写错误或非法值。

2. 布尔字面量(有时用于区分行为)

虽然 bool 本身只有 True/False,但有时为了明确意图:

from typing import Literal

def enable_feature(flag: Literal[True]) -> None:
    print("Feature enabled!")

# 只接受 True,不能传 False
enable_feature(True)   # ✅
# enable_feature(False)  # ❌ 类型错误

案例:

from typing import Literal, TypedDict

Method = Literal["GET", "POST", "PUT", "DELETE"]

class RequestConfig(TypedDict):
    url: str
    method: Method
    timeout: int

def send_request(config: RequestConfig) -> None:
    print(f"Sending {config['method']} request to {config['url']}")

# 正确
send_request({"url": "https://api.example.com", "method": "POST", "timeout": 10})

# 类型错误 ❌
# send_request({"url": "...", "method": "PATCH", ...})  # 'PATCH' 不被允许

Annotated

Annotated用于在保留主类型的同时,附加额外的元数据(metadata),而不会影响类型检查器对主类型的判断。

from typing import Annotated

VarType = Annotated[实际类型, 元数据1, 元数据2, ...]
  • 第一个参数:是变量的真实类型(如 strintList[str] 等),类型检查器(如 mypy)只关心这个。
  • 后续参数:是任意数量的元数据(metadata),可以是字符串、类、验证函数、文档说明、序列化配置等,运行时可用,但不影响类型检查

✅ 核心思想:“给类型加注释,而不改变类型本身”

示例:

from typing import Annotated

Username = Annotated[str, "用户名,长度 3-20 个字符"]

def create_user(name: Username) -> None:
    print(f"Creating user: {name}")

# 类型检查器仍认为 name 是 str
# 但开发者或工具可以读取后面的说明
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel

app = FastAPI()

# 使用 Annotated + Query 来定义 API 参数约束
@app.get("/items/")
def read_items(q: Annotated[str, Query(max_length=50, min_length=3)]):
    return {"q": q}

# 在 Pydantic 模型中
class UserCreate(BaseModel):
    name: Annotated[str, "用户真实姓名"]
    age: Annotated[int, "年龄,必须 >= 0"] = 18

💡 这里 Query(...) 就是一个元数据对象,FastAPI 会读取它来生成 OpenAPI 文档和做请求验证。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值