next()
函数有一个特殊的属性,即next(iterable)
返回元素或引发异常,而next(iterable, None)
返回元素或无。
如何输入注释?考虑以下事项,我正在使用 Pyright 进行检查:
from typing import TypeVar, Union
R = TypeVar('R')
class SuperNone:
pass
class MyDict:
data = { "a": 1 }
def get(
self, key: str, default: R = SuperNone
) -> Union[R, Elem] if R == SuperNone else Elem:
try:
return self.data[key]
except KeyError:
if isinstance(default, SuperNone):
raise
else:
return default
a: int = MyDict().get("a") # Expression of type "SuperNone | int" cannot be assigned to declared type "int"
b: Union[int, str] = MyDict().get("a", "")
# vs next() function is fine:
c: int = next((x for x in [1]))
d: Union[int, str] = next((x for x in [1]), "")
这不行,如何“动态”使返回打字值?
您可以使用
overload
来实现此输入。这不会影响运行时,重载签名专门用于类型检查器。以下是解决此问题的方法:
from typing import TypeVar, Union, Final, overload, Generic
_R = TypeVar('_R')
_T = TypeVar('_T')
_SENTINEL: Final = object()
class MyDict(Generic[_R]):
data: dict[str, _R]
def __init__(self, x: _R) ->None:
...
@overload
def get(self, key: str) -> _R: ...
@overload
def get(self, key: str, default: _T) -> _T | _R: ...
def get(
self, key: str, default: object = _SENTINEL
) -> _T | object:
try:
return self.data[key]
except KeyError:
if default is _SENTINEL:
raise
else:
return default
reveal_type(MyDict(1).get("a"))
reveal_type(MyDict(1).get("a", None))
reveal_type(MyDict(1).get("a", ""))
这里有一个 playground 链接(请注意,无需构建单独的类来创建独特的哨兵)
如果您不了解重载,那么您有一个很棒的东西 -
next
的工作示例。你可以去看看它的类型是如何定义的typeshed
:
@overload
def next(__i: SupportsNext[_T]) -> _T: ...
@overload
def next(__i: SupportsNext[_T], __default: _VT) -> _T | _VT: ...