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

主流Python类型检查器为何对Any注解出现漏报?

为何Python类型检查器对Any类型传入str参数的函数不报错?

我用4款常见Python类型检查器测试了以下代码片段,意外发现无一报错:

from typing import Any

def length(s: str) -> int:
    return len(s)

def any_length(o: Any) -> int:
    return length(o)

if __name__ == "__main__":
    print(any_length(1234))

但这段代码运行时会抛出明确异常:

TypeError: object of type 'int' has no len()

各检查器的结果如下:

  • mypy:
    Success: no issues found in 1 source file
    
  • pytype:
    Success: no errors found
    
  • pyright:
    0 errors, 0 warnings, 0 informations
    Completed in 0.435sec
    
  • pyre:
    ƛ No type errors found
    

我原本以为至少会收到警告,提示Any并非str的子类型,调用length(str->int)处理Any类型对象存在风险。为何这类简单场景下类型检查器无法识别?判断具体类型是否为另一类型的子类型似乎并非不可解,难道我理解有误?


原因解析

这是因为Any类型在Python类型系统里的特殊语义:它和所有类型是双向兼容的。也就是说:

  1. 任何类型的值都可以赋值给标注为Any的变量;
  2. 标注为Any的变量可以赋值给任何类型的变量,也可以直接传递给期望其他类型参数的函数。

类型检查器会将Any视为“类型检查的豁免区”——只要涉及Any,就会跳过类型兼容性验证。这是设计上的故意行为:Any的存在是为了处理动态场景、兼容无类型标注的代码,或者临时绕过类型检查。

如果想让检查器捕捉这类风险,应该避免使用Any,改用更精确的类型定义。比如用Protocol来描述具有__len__方法的类型:

from typing import Protocol

class Sized(Protocol):
    def __len__(self) -> int: ...

def length(s: Sized) -> int:
    return len(s)

def any_length(o: Sized) -> int:
    return length(o)

if __name__ == "__main__":
    print(any_length(1234))  # 此时类型检查器会报错,因为int没有__len__方法

这样类型检查器就能准确识别出不兼容的类型了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:55:15