Python:为 "has method" 输入提示
Python: Type Hint for "has method"
比如我们有一个class:
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)
很明显,不仅 class A
的实例可以作为 obj
参数传递,而且 socket.socket
的实例,也许其他 classes,已实施 recv
和 send
。
一个 annotate/type 怎么能暗示 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]
您真正需要的是 duck-typing (structural subtyping) via typing.Protocol. Some examples are in this list。
Protocol classes are defined like this:
class Proto(Protocol):
def meth(self) -> int:
...
Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing), for example:
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
An ABC with one abstract method __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)
- 请注意 ellipsis
...
并不意味着您必须将代码替换到其中。它真的应该如何。或者你也可以把 pass
放在那里如果 3 个点很烦 :)
比如我们有一个class:
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)
很明显,不仅 class A
的实例可以作为 obj
参数传递,而且 socket.socket
的实例,也许其他 classes,已实施 recv
和 send
。
一个 annotate/type 怎么能暗示 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]
您真正需要的是 duck-typing (structural subtyping) via typing.Protocol. Some examples are in this list。
Protocol classes are defined like this:
class Proto(Protocol): def meth(self) -> int: ...
Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing), for example:
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
An ABC with one abstract method
__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)
- 请注意 ellipsis
...
并不意味着您必须将代码替换到其中。它真的应该如何。或者你也可以把pass
放在那里如果 3 个点很烦 :)