Python 为支持 __getitem__ 的 类 输入提示
Python type hint for classes that support __getitem__
我想向函数添加类型提示,该函数将接受任何具有 __getitem__
方法的对象。例如,在
def my_function(hasitems, locator):
hasitems[locator]
我不想将 hasitems
限制为特定类型,例如 list
或 dict
。只要它支持 __getitem__
,它就是 my_function
的适当参数。我怎样才能在没有不必要限制的情况下注释它的类型?
编辑:显然 PyCharm 可以在许多常见情况下推断出适当的提示,但在我的实际用例中却没有。我不能 post 代码,因为它是为了工作,而且我一直没能找到 PyCharm 失败的非专有最小示例。在任何情况下,原始问题都没有引用 PyCharm 并且它仍然是类型提示的有效用例。
这适用于字典和列表,但不适用于任何泛型:
from typing import Any, Mapping, Sequence, Union
def my_function(hasitems: Union[Mapping, Sequence], locator: Any) -> Any:
return hasitems[locator]
听起来您基本上想定义自己的 abstract base class (abc)。
按照上面的文档,您可以定义一个自定义 abc,它只指示 __getitem__
的存在,但让我们使用一个预定义的作为示例。
Mapping
abc 由 __getitem__
和其他一些魔术方法组成。你可以在isinstance
中使用abcs,但你也可以直接将它们用作类型注释:
def foo(bar: Mapping):
pass
或者,使用 extended type hinting support of ABCs 甚至可以做一些你已经在其他答案中看到的奇特的事情:
def foo(bar: Mapping[Any, Any]):
pass
如果您愿意为 typing
安装一个不太正式的扩展,typing-extensions, you can use a Protocol
, which should be an implementation of PEP-0544:
from typing_extensions import Protocol
from typing import Any
class GetItem(Protocol):
def __getitem__(self: 'Getitem', key: Any) -> Any: pass
class BadGetItem:
def __getitem__(self, a: int, b: int) -> Any: pass
def do_thing(arg: GetItem):
pass
do_thing(dict()) # OK
do_thing(BadGetItem()) # Fails with explanation of correct signature
do_thing(1) # Fails
我想向函数添加类型提示,该函数将接受任何具有 __getitem__
方法的对象。例如,在
def my_function(hasitems, locator):
hasitems[locator]
我不想将 hasitems
限制为特定类型,例如 list
或 dict
。只要它支持 __getitem__
,它就是 my_function
的适当参数。我怎样才能在没有不必要限制的情况下注释它的类型?
编辑:显然 PyCharm 可以在许多常见情况下推断出适当的提示,但在我的实际用例中却没有。我不能 post 代码,因为它是为了工作,而且我一直没能找到 PyCharm 失败的非专有最小示例。在任何情况下,原始问题都没有引用 PyCharm 并且它仍然是类型提示的有效用例。
这适用于字典和列表,但不适用于任何泛型:
from typing import Any, Mapping, Sequence, Union
def my_function(hasitems: Union[Mapping, Sequence], locator: Any) -> Any:
return hasitems[locator]
听起来您基本上想定义自己的 abstract base class (abc)。
按照上面的文档,您可以定义一个自定义 abc,它只指示 __getitem__
的存在,但让我们使用一个预定义的作为示例。
Mapping
abc 由 __getitem__
和其他一些魔术方法组成。你可以在isinstance
中使用abcs,但你也可以直接将它们用作类型注释:
def foo(bar: Mapping):
pass
或者,使用 extended type hinting support of ABCs 甚至可以做一些你已经在其他答案中看到的奇特的事情:
def foo(bar: Mapping[Any, Any]):
pass
如果您愿意为 typing
安装一个不太正式的扩展,typing-extensions, you can use a Protocol
, which should be an implementation of PEP-0544:
from typing_extensions import Protocol
from typing import Any
class GetItem(Protocol):
def __getitem__(self: 'Getitem', key: Any) -> Any: pass
class BadGetItem:
def __getitem__(self, a: int, b: int) -> Any: pass
def do_thing(arg: GetItem):
pass
do_thing(dict()) # OK
do_thing(BadGetItem()) # Fails with explanation of correct signature
do_thing(1) # Fails