Pyright字面量穷尽检查为何仅支持参数,不支持类属性?
Pyright穷尽检查的差异原因
以下代码可正常通过Pyright的穷尽检查:
from typing import Literal def test(it: Literal['a', 'b']) -> str: if it == 'a': return 'a' elif it == 'b': return 'b' # No error, exhaustive
但下方代码无法通过检查:
from dataclasses import dataclass from typing import Literal @dataclass class Foo: foo: Literal['a', 'b'] def test(it: Foo) -> str: foo = it.foo if foo == 'a': return 'a' elif foo == 'b': # Correctly infers that foo is Literal['b'] without the check return 'b' # Error, must return str
差异核心原因
这是Pyright对变量不可变性的推导逻辑差异导致的:
- 第一个例子里,
it是直接传入的函数参数,类型为Literal['a','b']。Pyright会认定这类参数是不可变的——函数执行过程中它的类型和值不会被修改,因此在覆盖了'a'和'b'两个分支后,Pyright能确定已经穷尽了所有可能的取值,不会触发“未返回值”的错误。 - 第二个例子里,
foo是从数据类实例中提取的局部变量。Pyright默认不会假设数据类的属性是完全不可变的(哪怕你没定义setter,静态分析阶段也无法100%排除其他代码修改该属性的可能)。因此Pyright会保留“foo的类型可能被意外改变”的可能性,不会认为两个分支已经覆盖了所有情况,最终提示函数可能没有返回值的错误。
内容的提问来源于stack exchange,提问作者Anthony Naddeo
相关产品推荐
相关产品推荐

