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

使用mypy 1.2.0对移除空字段的列表排序时遇类型错误,如何解决?

问题:mypy无法识别过滤后列表的非空类型,导致sorted报错

在使用mypy 1.2.0的Python项目中,执行以下代码的lint检查:

from datetime import date, timedelta
from typing import Optional

from pydantic import BaseModel


class ScheduleItem(BaseModel):
    start_date: Optional[date] = None


items = [
    ScheduleItem(start_date=None),
    ScheduleItem(start_date=date.today()),
    ScheduleItem(start_date=date.today() - timedelta(days=3)),
]


sorted_items = sorted(
    [item for item in items if item.start_date],
    key=lambda item: item.start_date,
)

得到如下错误:

error: Argument "key" to "sorted" has incompatible type "Callable[[ScheduleItem], Optional[date]]"; expected "Callable[[ScheduleItem], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]"  [arg-type]

error: Incompatible return value type (got "Optional[date]", expected "Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]")  [return-value]

尽管传入sorted的列表已经通过过滤确保start_date不为None,但mypy无法识别这一非空状态,请问如何解决?


解决方案

方法1:使用类型断言(cast)

在lambda表达式中对start_date做非空断言,明确告知mypy此时该值不可能为None:

from typing import cast

sorted_items = sorted(
    [item for item in items if item.start_date],
    key=lambda item: cast(date, item.start_date),
)

方法2:给过滤后的列表添加显式类型注解

通过注解明确过滤后的列表元素类型,让mypy知晓其中的ScheduleItem的start_date非空:

from typing import List

# 定义start_date非空的子类,明确类型约束
class NonNullScheduleItem(ScheduleItem):
    start_date: date

filtered_items: List[NonNullScheduleItem] = [item for item in items if item.start_date]
sorted_items = sorted(filtered_items, key=lambda item: item.start_date)

或者直接用cast标注过滤后的列表类型:

filtered_items = cast(List[ScheduleItem], [item for item in items if item.start_date])
sorted_items = sorted(filtered_items, key=lambda item: item.start_date)

方法3:自定义类型守卫(Type Guard)

编写类型守卫函数,让mypy能通过该函数识别start_date非空的ScheduleItem:

from typing import TypeGuard

def has_non_null_start_date(item: ScheduleItem) -> TypeGuard[ScheduleItem]:
    return item.start_date is not None

sorted_items = sorted(
    [item for item in items if has_non_null_start_date(item)],
    key=lambda item: item.start_date,
)

方法4:升级mypy版本

mypy 1.3及后续版本优化了列表推导式的类型推断逻辑,能够自动识别过滤后的非空状态。如果项目允许,直接升级mypy即可解决问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:57:27