gpt4 book ai didi

python - 通用迭代器注释 Python

转载 作者:行者123 更新时间:2023-12-05 08:03:03 24 4
gpt4 key购买 nike

我正在尝试注释一个只​​返回两个值的迭代器,Tcls[T]

目前我有这样的注释:

from __future__ import annotations
import typing


class Node(typing.Generic[T]):
def __init__(self, value: T, next: typing.Optional[Node[T]] = None) -> None:
self.value = value
self.next = next

def __iter__(self) -> typing.Iterator[typing.Union[T, Node[T]]]:
yield from (self.value, self.next)

这段代码没有任何错误。但是,我希望利用这个 dunder 方法总是产生两个值这一事实来简化用户的过程。

实际上,用户必须处理以下内容:

one = Node[int](1, Node[int](2))
value, next = one # value = 1, next = Node(2) (i.e one.next)

# This is a typing error because next can be either int or Node[int]
# and 'two' is expected to be Node[int]:
two: Node[int] = next

# we can fix this by doing type narrowing
assert isinstance(next, Node)
two = next # now the error should be gone

所以基本上我想利用这样一个事实,即 __iter__ 返回的第二个东西总是类型 Node[T] 以避免必须进行类型缩小.

我知道我必须在方法的返回注释中更改 typing.Union[T, Node[T]],但我不知道将其更改为什么。

最佳答案

这不可能使用通用的 Iterator 进行注释。它是一个需要 one 类型参数的类。 (当前 typeshed source )这意味着其 __next__ 方法返回的每个 值必须具有相同的类型。

您正在 self.value, self.next 元组上调用迭代器协议(protocol)。一个元组有任意 数量的类型参数(参见 here ),但它上面的迭代器必须只有一个。这实际上经常导致打字问题。

由于您似乎打算让您的 Node 类从本质上模拟 tuple 接口(interface),这可能是极少数情况之一,最好直接从它继承. tuple 显然也会为您提供可迭代协议(protocol),因此您仍然可以像以前一样解压它,但是如果您做的一切都正确,则应该正确推断类型。

这是一个完整的工作示例:

from __future__ import annotations
from typing import TypeVar, Optional


T = TypeVar("T")


class Node(tuple[T, "Node[T]"]):
def __new__(cls, value: T, next_: Optional[Node[T]] = None) -> Node[T]:
return tuple.__new__(cls, (value, next_))

def __init__(self, value: T, next_: Optional[Node[T]] = None) -> None:
self.value = value
self.next = next_


if __name__ == "__main__":
node_1 = Node(1, Node(2))
val: int
node_2: Node[int]
val, node_2 = node_1

这通过了 mypy --strict 没有问题。


作为不相关的旁注,我建议不要使用内置名称,如 next .

另外,请注意,当您初始化一个节点时,您不需要为 Node 指定类型参数,因为它会自动绑定(bind)到传递给 的类型>值参数。

关于python - 通用迭代器注释 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74696410/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com