如何为无类型提示/存根的库指定函数返回类型?
无类型存根库的返回类型标注优化方案
当导入缺少类型存根的库时,用# type: ignore会让mypy将该模块的所有返回类型视为Any,导致定义返回类型时只能用宽泛的Any。以你提供的Plotly示例为例:
import plotly.express as px # type: ignore from plotly import graph_objects as go from pandas import DataFrame def plot_df(df: DataFrame) -> go.Figure: return px.bar(data_frame=df)
触发mypy错误:error: Return type becomes "Any" due to an unfollowed import [no-any-unimported],以下是几种更优的解决方法:
1. 安装社区维护的第三方类型存根
多数流行库都有社区维护的类型存根包,Plotly的类型存根可以通过以下命令安装:
pip install types-plotly
安装后,移除导入语句后的# type: ignore,mypy就能正常识别px.bar的返回类型为go.Figure,原代码无需修改即可通过类型检查。
2. 手动编写局部类型存根
如果没有现成的第三方存根,可以在项目目录下创建对应模块的存根文件(.pyi)。比如创建plotly/express.pyi,内容如下:
from plotly.graph_objs._figure import Figure from pandas import DataFrame def bar(data_frame: DataFrame) -> Figure: ...
这个存根只需要定义你用到的函数和返回类型,mypy会读取该文件识别类型,无需忽略模块导入。
3. 用Protocol定义接口类型
如果不想依赖存根,可以通过Protocol定义一个匹配目标对象接口的类型,只声明你实际用到的方法:
from typing import Protocol from pandas import DataFrame class FigureLike(Protocol): def show(self) -> None: ... # 根据需求添加其他你调用的方法,如write_html等 def plot_df(df: DataFrame) -> FigureLike: import plotly.express as px return px.bar(data_frame=df)
这样既避免了Any的宽泛性,又能让mypy检查返回值是否符合你定义的接口。
4. 精准忽略单个导入项(而非整个模块)
如果只是模块内部分函数无类型,可以只忽略特定导入:
from plotly.express import bar # type: ignore from plotly import graph_objects as go from pandas import DataFrame def plot_df(df: DataFrame) -> go.Figure: return bar(data_frame=df)
这种方式比忽略整个模块更精准,减少Any的范围。
内容的提问来源于stack exchange,提问作者Ahko26
相关产品推荐
相关产品推荐

