You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Polars自定义命名空间注册后如何规避mypy/pyright类型错误?

问题

在使用Polars注册自定义命名空间函数时,mypy或pyright会持续抛出类型错误,除了每次调用时添加# type: ignore[attr-defined]注解,有没有其他方法规避这些类型检查器错误?

以下是示例代码(文件checker.py):

import polars as pl

@pl.api.register_expr_namespace("greetings")
class Greetings:
    def __init__(self, expr: pl.Expr):
        self._expr = expr

    def hello(self) -> pl.Expr:
        return (pl.lit("Hello ") + self._expr).alias("hi there")

    def goodbye(self) -> pl.Expr:
        return (pl.lit("Sayōnara ") + self._expr).alias("bye")


print(pl.DataFrame(data=["world", "world!", "world!!"]).select(
    [
        pl.all().greetings.hello(), # type: ignore[attr-defined]
        pl.all().greetings.goodbye(),
    ]
))

执行mypy检查的输出:

% mypy checker.py
checker.py:19: error: "Expr" has no attribute "greetings"  [attr-defined]
Found 1 error in 1 file (checked 1 source file)
% mypy --version
mypy 1.8.0 (compiled: yes)

执行pyright检查的输出:

% pyright checker.py
/path/to/checker.py
  /path/to/checker.py:19:18 - error: Cannot access member "greetings" for type "Expr"
    Member "greetings" is unknown (reportGeneralTypeIssues)
1 error, 0 warnings, 0 informations
% pyright --version
pyright 1.1.343

解决方案

方法1:添加类型扩展Stub文件

给Polars的Expr类型补充自定义命名空间的类型注解,创建一个.pyi格式的Stub文件(比如polars_ext.pyi):

import polars as pl

class Greetings:
    def __init__(self, expr: pl.Expr) -> None: ...
    def hello(self) -> pl.Expr: ...
    def goodbye(self) -> pl.Expr: ...

class Expr(pl.Expr):
    greetings: Greetings

然后在主代码顶部引入该扩展类型(仅用于类型检查):

from polars_ext import Expr  # type: ignore[import]

也可以在mypy.ini或pyrightconfig.json中配置Stub文件路径,让类型检查器自动识别扩展。

方法2:使用类型断言

定义包含自定义命名空间的类型,调用前将表达式断言为该类型:

from typing import cast

class ExprWithGreetings(pl.Expr):
    greetings: Greetings

# 调用时
expr = cast(ExprWithGreetings, pl.all())
expr.greetings.hello()

方法3:针对性修改类型检查器配置

在配置文件中对特定文件或规则禁用相关检查,避免全局影响:

  • mypy:在mypy.ini中添加
    [mypy-checker]
    # 仅禁用attr-defined错误
    disable_error_codes = attr-defined
    
  • pyright:在pyrightconfig.json中添加
    {
      "reportGeneralTypeIssues": false
    }
    

注意:此方法会放宽类型检查精度,建议仅在目标文件/模块中启用。

方法4:封装为普通函数

将自定义命名空间的调用封装成普通函数,仅在封装内部添加一次忽略注解:

def greetings_hello(expr: pl.Expr) -> pl.Expr:
    return expr.greetings.hello()  # type: ignore[attr-defined]

def greetings_goodbye(expr: pl.Expr) -> pl.Expr:
    return expr.greetings.goodbye()  # type: ignore[attr-defined]

# 调用时无需再加注解
print(pl.DataFrame(data=["world", "world!", "world!!"]).select(
    [
        greetings_hello(pl.all()),
        greetings_goodbye(pl.all()),
    ]
))

内容的提问来源于stack exchange,提问作者lisonator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:45:18