【问题标题】:Python: Type Hint for "has method"Python:为“有方法”键入提示
【发布时间】:2021-11-04 12:23:15
【问题描述】:

例如,我们有一个类:

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 的实例也可以传递,可能还有其他类,它们实现了recvsend

如何注释/键入提示 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]

【问题讨论】:

    标签: python types annotations type-hinting python-typing


    【解决方案1】:

    您真正需要的是duck-typing(结构子类型)通过typing.Protocol。这个list中有一些例子。

    协议类是这样定义的:

    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__的ABC。

    所以对于你的情况,它可能是这样的:

    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 放在那里,如果这三个点很麻烦的话:)

    【讨论】:

      猜你喜欢
      • 2019-05-28
      • 2017-09-27
      • 2020-11-23
      • 2021-08-03
      • 2017-08-03
      • 2022-01-04
      相关资源
      最近更新 更多