Python中可通过**运算符解包对象的正确类型注解是什么?
Python中**运算符可解包对象的类型注解方案
首先明确:Python中**运算符要求对象满足类映射(mapping-like)行为——即可以迭代获取键,且能通过键索引取值。但标准库的typing.Mapping抽象基类无法覆盖所有这类对象(比如pandas的Series,虽然能被**解包,但isinstance(Series({"a":1}), Mapping)返回False,因为它没继承Mapping)。
以下是几种可行的类型注解方案:
1. 直接指定已知类型(简单场景)
如果你的函数只需要支持dict和pandas.Series,直接用联合类型最直观:
from pandas import Series from typing import Dict def my_function(unpackable: Dict | Series) -> None: {**unpackable}
2. 自定义协议(通用场景)
要覆盖所有符合**解包要求的对象,推荐用typing.Protocol定义一个抽象协议,只要对象实现了协议要求的方法,就会被类型检查器识别为合法输入:
from typing import Protocol, Iterator, Hashable import pandas as pd class Unpackable(Protocol): """定义支持**解包的对象协议""" def __iter__(self) -> Iterator[Hashable]: # 返回可迭代的键(需为可哈希类型) ... def __getitem__(self, key: Hashable) -> object: # 支持通过键索引取值 ... def my_function(unpackable: Unpackable) -> None: {**unpackable}
这个协议适配所有能被**解包的对象,包括dict、pandas.Series,以及你自己实现的类(只要满足迭代键+索引取值的行为)。
3. 避免使用Any
虽然typing.Any能绕过类型检查,但会失去类型注解的意义,不推荐在需要类型安全的场景使用。
内容的提问来源于stack exchange,提问作者michen00
相关产品推荐
相关产品推荐

