如何根据是否给出参数(如 next() 函数的情况)来键入注释不同的返回类型?

问题描述 投票:0回答:1

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]), "")

这不行,如何“动态”使返回打字值?

python-3.x python-typing typing
1个回答
0
投票

您可以使用

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: ...
© www.soinside.com 2019 - 2024. All rights reserved.