You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python:如何对拥有指定方法的对象参数添加Type Hint类型标注

Python 鸭子类型参数的类型标注方案

你可以通过Python的结构子类型(Structural Subtyping) 实现需求,优先推荐使用typing.Protocol(Python 3.8及以上版本内置支持,3.7及更早版本需安装typing-extensions第三方包),无需修改原有类的继承关系,完美适配鸭子类型的使用场景。

具体实现步骤

  1. 先定义符合要求的协议类
from typing import Protocol

class SendRecvProtocol(Protocol):
    # 协议类不需要写具体实现,仅定义方法签名即可
    def send(self, msg: bytes) -> None: ...
    def recv(self, n: int) -> bytes: ...
  1. 直接给函数参数加标注即可
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 20:45:04