#python #types #annotations #type-hinting #python-typing
Вопрос:
Например, у нас есть класс:
class A:
def send(msg: bytes) -> None:
# implementation...
pass
def recv(n: int) -> bytes:
# implementation
pass
и функция:
def a(obj, n: int) -> None:
received = obj.recv(n)
obj.send(received)
Довольно очевидно, что A
в качестве аргумента могут быть переданы не только экземпляры класса obj
, но и экземпляры socket.socket
, возможно, других классов, которые имеют recv
и send
реализованы.
Как можно аннотировать/вводить obj
аргумент подсказки, чтобы он говорил что-то вроде:
obj type must possess methods send and recv
send method must be of type Callable[[bytes], None]
recv method must be of type Callable[[int], bytes]
Ответ №1:
Что вам точно нужно, так это типизация утки (структурный подтип) с помощью набора текста.Протокол. Некоторые примеры приведены в этом списке.
Классы протоколов определяются следующим образом:
class Proto(Protocol): def meth(self) -> int: ...
Такие классы в основном используются для проверки статических типов, которые распознают структурные подтипы (статическая утиная типизация), например:
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
Где встроенный пример
class typing.SupportsIndex
Азбука с одним абстрактным методом
__index__
.
Так что для вашего случая это может быть что-то вроде:
from typing import Protocol
class SupportsSendReceive(Protocol):
def send(self, msg: bytes) -> None:
...
def recv(self, n: int) -> bytes:
...
def a(obj: SupportsSendReceive, n: int) -> None:
received = obj.recv(n)
obj.send(received)
- Обратите внимание, что многоточие
...
не означает, что вы должны вставлять в него код. Это действительно так, как должно быть. Или вы также можете вставитьpass
туда, если вас беспокоят 3 точки 🙂