如何为自定义类型的__iter__方法添加注释以正确指示非统一的返回类型?

12 浏览
0 Comments

如何为自定义类型的__iter__方法添加注释以正确指示非统一的返回类型?

我有一个自定义类型,希望能够解包它的值(类似于元组解包等)。我在Python中知道的最简单的方法是实现`__iter__`。在运行时,这个方法运行得很好,但是我希望能够提供类型注解,以便为每个项目返回正确的类型,例如:\n

import typing as t
from dataclasses import dataclass
@dataclass
class Foo:
    a: str
    b: bool
    
    def __iter__(self) -> t.Iterable[str, bool]:
        yield self.a
        yield self.b

\n在运行时,这个方法按预期工作:\n

string, bool = Foo("Hello", False)

\n然而,上面的`string`和`bool`被报告为`Any`类型。有没有一种合理的方式来提供这种用例,同时保留类型信息?\n这个实际类型不容易转换为`NamedTuple`等。\n类似于[如何注释多个返回值的类型?](https://stackoverflow.com/questions/40181344/how-to-annotate-types-of-multiple-return-values)

0
0 Comments

问题的原因是想要为自定义类型的__iter__方法添加类型注释,以正确指示返回的非统一类型。解决方法是通过调整类型检查器使其认为自定义类实际上是一个元组子类,这样它在解包时会得到类似的处理。

具体解决方法如下:

1. 导入必要的模块和库:

import typing as t
from dataclasses import dataclass

2. 定义一个基类,根据是否在类型检查模式下做特殊处理:

if t.TYPE_CHECKING:
    base = tuple[str, bool]
else:
    base = object

3. 定义一个自定义类,继承基类,并添加类变量和方法:

class Foo(base):
    a: str
    b: bool
    
    def __iter__(self) -> t.Iterator[str | bool]:
        yield self.a
        yield self.b

4. 在主程序中使用自定义类,并对其进行解包和类型检查:

p, q = Foo('a', True)
reveal_type(p)
reveal_type(q)

上述代码中的`typing.TYPE_CHECKING`是一个特殊的常量,在运行时为`False`(因此其中的代码不会执行),但在类型检查器中为`True`。

这种解决方法非常棒,但可能不适合在实际生产代码中使用。

0