Python静态类型提示/检查Iterable[AnyStr]与Iterable[str] | Iterable[byt



我遇到了这个静态类型提示不匹配(与Pyright):

from __future__ import annotations
from typing import AnyStr, Iterable

def foo(i: Iterable[AnyStr]):
return i

def bar(i: Iterable[str] | Iterable[bytes]):
return i

def baz(i: Iterable[str | bytes]):
return i

def main():
s = ['a']
# makes sense to me
baz(foo(s))  # allowed
foo(baz(s))  # not allowed
# makes sense to me
baz(bar(s))  # allowed
bar(baz(s))  # not allowed
bar(foo(s))  # allowed
foo(bar(s))  # nope -- why?

Iterable[AnyStr]Iterable[str] | Iterable[bytes]的区别是什么?

它们不应该是"相等的"吗?(除了AnyStr在上下文中引用单一一致类型)

更具体地说:什么是正确的方式来输入提示以下内容?

import random
from typing import Iterable, AnyStr
def foo(i: Iterable[AnyStr]):
return i
def exclusive_bytes_or_str():  # type-inferred to be Iterator[bytes] | Iterator[str]
if random.randrange(2) == 0:
return iter([b'bytes'])
else:
return iter(['str'])
foo(iter([b'bytes']))          # fine
foo(iter(['str']))             # fine
foo(exclusive_bytes_or_str())  # same error

转述自erictraut@github:

这并不是约束TypeVar的真正用途。我建议使用@overload来代替:

@overload
def foo(i: Iterable[str]) -> Iterable[str]: ...
@overload
def foo(i: Iterable[bytes]) -> Iterable[bytes]: ...
def foo(i: Iterable[AnyStr]) -> Iterable[AnyStr]:
return i

因为:

类型Iterable[str] | Iterable[bytes]不能赋值给类型Iterable[AnyStr]。约束类型变量需要匹配它的一个约束,而不是多个约束。当一个类型变量被"解决"时,它需要被另一个(通常是具体的)类型替换。如果允许foo(bar(s)),那么AnyType@foo类型变量解析为什么类型?如果它被解析为str | bytes类型,那么foo的具体返回类型将是Iterable[str | bytes]。这显然是错误的。

最新更新