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

非整数切片与类型检查:时间序列日期切片的mypy兼容方案

时间序列datetime切片的mypy类型检查问题

我在处理时间序列数据时,希望通过日期/时间进行检索和切片,复用Python原生的[:]语法。示例代码如下:

from datetime import datetime
from typing import Union


class T:
    def __getitem__(self, key: datetime | slice) -> Union['T', float]:
        if isinstance(key, slice):
            return T()
        if isinstance(key, datetime):
            return 42
        raise ValueError()


t = T()
v = t[datetime(2020, 1, 1)]                        # 正常运行
t2 = t[datetime(2020, 1, 1):datetime(2021, 1, 1)]  # mypy报错

这段代码能正常运行,但通过mypy检查时,最后一行会出现如下错误:

error: Slice index must be an integer, SupportsIndex or None  [misc]
Found 1 error in 1 file (checked 1 source file)

除了完全禁用该错误外,有没有办法让这段代码通过mypy检查?或者我的做法本身存在问题?


解决方法

1. 使用带类型参数的slice注解(Python 3.10+)

mypy支持带类型参数的slice类型注解,明确指定切片的start/stop/step允许为datetime或None,修改__getitem__的参数类型即可通过检查:

from datetime import datetime
from typing import Union


class T:
    def __getitem__(self, key: Union[datetime, slice[datetime | None]]) -> Union['T', float]:
        if isinstance(key, slice):
            return T()
        if isinstance(key, datetime):
            return 42
        raise ValueError()


t = T()
v = t[datetime(2020, 1, 1)]
t2 = t[datetime(2020, 1, 1):datetime(2021, 1, 1)]  # mypy不再报错

2. 行内忽略特定错误(最小化禁用范围)

如果不想修改类型注解,可以在报错行添加# type: ignore[misc]注释,仅忽略这一行的切片索引检查,不影响其他代码:

t2 = t[datetime(2020, 1, 1):datetime(2021, 1, 1)]  # type: ignore[misc]

3. 自定义支持索引的datetime子类

若需要更严格的类型合规,可创建继承自datetime的子类,实现__index__方法以满足SupportsIndex协议,mypy会认可其作为切片索引:

from datetime import datetime
from typing import Union


class DatetimeIndex(datetime):
    def __index__(self) -> int:
        # 将datetime转换为时间戳整数作为索引值
        return int(self.timestamp())


class T:
    def __getitem__(self, key: DatetimeIndex | slice[DatetimeIndex | None]) -> Union['T', float]:
        if isinstance(key, slice):
            return T()
        if isinstance(key, DatetimeIndex):
            return 42
        raise ValueError()


t = T()
v = t[DatetimeIndex(2020, 1, 1)]
t2 = t[DatetimeIndex(2020, 1, 1):DatetimeIndex(2021, 1, 1)]  # mypy正常通过

用法合理性说明

用datetime作为时间序列的索引和切片边界是时间序列处理中的常规需求(例如pandas就支持datetime索引的切片操作),你的思路本身没有问题。mypy的报错只是因为它默认要求切片索引必须是整数、实现SupportsIndex协议的类型或None,通过上述方法即可让类型检查工具认可你的用法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 10:28:13