如何在类型提示中指定联合类型的可选值?
这个问题问得太贴合实际了!我之前在写类似的数据分析工具函数时,也纠结过怎么把联合类型参数的可选值清晰地传达给用户,刚好可以分享下常用的几种方案:
1. 文档字符串是必选项:给所有用户看的说明
类型提示(比如Union[int, str])只能告诉用户参数的类型范围,但没法限定具体的合法值——就像你提到的pandas dropna的axis参数,int类型的话只能是0或1,str类型只能是'index'或'columns',这些细节必须写在文档字符串里,才能让所有使用这个函数的用户一眼看明白。
推荐用行业通用的文档字符串风格(比如Google、NumPy或reStructuredText风格),把可选值明确列出来:
from typing import Union import pandas as pd def dropna(self, axis: Union[int, str] = 0) -> pd.DataFrame: """移除数据中的缺失值。 参数 ---------- axis : int 或 str, 默认值 0 指定移除包含缺失值的行还是列,可选值: - 0 或 'index':移除包含缺失值的行 - 1 或 'columns':移除包含缺失值的列 返回 ------- pandas.DataFrame 移除缺失值后的新DataFrame """ # 函数实现逻辑
2. 用Literal类型做静态校验:给类型检查工具用的约束
如果你希望静态类型检查工具(比如mypy、Pyright)能直接校验用户传入的参数是否合法,避免他们传入2、'rows'这种不合法的值,那可以用Python 3.8+引入的Literal类型(3.8以下可以用typing_extensions里的Literal),把参数的合法值直接写在类型提示里:
from typing import Union, Literal import pandas as pd def dropna(self, axis: Union[Literal[0, 1], Literal['index', 'columns']] = 0) -> pd.DataFrame: """移除数据中的缺失值。 参数 ---------- axis : {0, 1, 'index', 'columns'}, 默认值 0 指定移除包含缺失值的行还是列: - 0/'index':移除行 - 1/'columns':移除列 返回 ------- pandas.DataFrame 移除缺失值后的新DataFrame """ # 函数实现逻辑
或者更简洁的写法,因为Literal支持混合不同类型的字面量:
axis: Literal[0, 1, 'index', 'columns'] = 0
这样一来,用户如果传入axis=2这种不合法的值,类型检查工具会直接抛出警告,提前帮用户规避错误。
3. 用领域封装类型:比如pandas自带的Axis
像pandas这种成熟的库,已经为常用的参数类型做了封装,比如Axis类型,它本身就已经包含了0、1、'index'、'columns'这些合法值的约束,直接用它作为类型提示会更简洁:
from pandas.core.dtypes.common import Axis import pandas as pd def dropna(self, axis: Axis = 0) -> pd.DataFrame: """移除数据中的缺失值。 参数 ---------- axis : Axis, 默认值 0 指定移除包含缺失值的行还是列,支持传入0/'index'(行)或1/'columns'(列) 返回 ------- pandas.DataFrame 移除缺失值后的新DataFrame """ # 函数实现逻辑
总结
最稳妥的方案是把Literal类型提示和详细的文档字符串结合起来:Literal负责静态类型校验,帮开发者提前发现错误;文档字符串负责给所有用户(包括不使用类型检查工具的人)清晰说明可选值。如果是在特定领域(比如pandas),直接用库自带的封装类型会更高效。
内容来源于stack exchange

