问题
I want to add type hints to a function that will accept any object with a __getitem__
method. For instance, in
def my_function(hasitems, locator):
hasitems[locator]
I don't want to restrict hasitems
to be a specific type like list
or dict
. As long as it supports __getitem__
, it's an appropriate argument to my_function
. How can I annotate its type without being unnecessarily restrictive?
Edit: apparently PyCharm can deduce the appropriate hint in a number of common cases, but not in my actual use case. I can't post the code since it's for work, and I haven't been able to find a nonproprietary minimal example where PyCharm fails. In any case, the original question doesn't reference PyCharm and it is still a valid use case for type hints.
回答1:
If you're willing to install a not-quite-offical extension to 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
回答2:
It sounds like you essentially want to define your own abstract base class (abc).
Following the documentation above, you can define a custom abc that only dictates the presence of __getitem__
, but let's use a predefined one for an example.
The Mapping abc consists of __getitem__
and a few other magic methods. You can use abcs in isinstance
, but you can also directly use them as a type annotations:
def foo(bar: Mapping):
pass
Or, using the extended type hinting support of ABCs do even fancies things, which you already saw in other answers:
def foo(bar: Mapping[Any, Any]):
pass
回答3:
This will work for dict and list, but not for any generic type:
from typing import Any, Mapping, Sequence, Union
def my_function(hasitems: Union[Mapping, Sequence], locator: Any) -> Any:
return hasitems[locator]
来源:https://stackoverflow.com/questions/55127855/python-type-hint-for-classes-that-support-getitem