Python:如何对拥有指定方法的对象参数添加Type Hint类型标注
Python 鸭子类型参数的类型标注方案
你可以通过Python的结构子类型(Structural Subtyping) 实现需求,优先推荐使用typing.Protocol(Python 3.8及以上版本内置支持,3.7及更早版本需安装typing-extensions第三方包),无需修改原有类的继承关系,完美适配鸭子类型的使用场景。
具体实现步骤
- 先定义符合要求的协议类
from typing import Protocol class SendRecvProtocol(Protocol): # 协议类不需要写具体实现,仅定义方法签名即可 def send(self, msg: bytes) -> None: ... def recv(self, n: int) -> bytes: ...
- 直接给函数参数加标注即可
def a(obj: SendRecvProtocol, n: int) -> None: received = obj.recv(n) obj.send(received)
方案说明
- 只要任意类实现了签名匹配的
send和recv方法,不管有没有显式继承SendRecvProtocol,都会被类型检查器(比如mypy、pyright)自动识别为符合协议类型,你自定义的A类、标准库socket.socket实例都可以直接传入,不需要做额外修改 - 类型检查器会自动校验
send和recv的参数、返回值是否符合要求,不匹配会直接抛出类型错误,完全满足你提出的3项要求
兼容旧版本Python的替代方案
如果你使用的是Python 3.7及更早版本,也可以用抽象基类实现,不过需要手动做继承/注册操作,适配成本更高:
from abc import ABC, abstractmethod import socket # 定义抽象基类 class SendRecvBase(ABC): @abstractmethod def send(self, msg: bytes) -> None: pass @abstractmethod def recv(self, n: int) -> bytes: pass # 手动注册第三方类到抽象基类 SendRecvBase.register(socket.socket) # 自定义类需要显式继承 class A(SendRecvBase): def send(msg: bytes) -> None: pass def recv(n: int) -> bytes: pass # 标注方法和协议方案一致 def a(obj: SendRecvBase, n: int) -> None: received = obj.recv(n) obj.send(received)
内容的提问来源于stack exchange,提问作者winwin
相关产品推荐
相关产品推荐

