You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Mypy技巧:如何为返回类型依赖于参数类型的函数添加类型注解

解决Mypy中多场景除法的类型注解问题

当然可以!Mypy支持通过@overload装饰器来为同一个函数定义多个不同的签名,刚好能解决你这种除法操作的双场景类型注解需求。下面是具体的实现方案:

步骤1:导入必要工具

首先需要从typing模块(Python 3.8+)或者typing_extensions(兼容更早Python版本)导入overloadUnion

from typing import overload, Union
from enum import Enum
from pydantic import BaseModel

步骤2:为__truediv__定义重载签名

在实现实际的除法方法前,先通过@overload为两种场景分别定义类型签名——注意重载的函数只需要写类型注解,不需要实现逻辑,实际逻辑统一写在最后一个无@overload装饰的函数里:

class MemoryUnit(Enum):
    """Units of memory."""
    GB = 'GB'
    TB = 'TB'
    PB = 'PB'

class Memory(BaseModel):
    """Normalized amount of memory."""
    amount: int
    unit: MemoryUnit

    def __add__(self, other: 'Memory') -> 'Memory':
        # 示例加法逻辑:需保证单位一致
        if self.unit != other.unit:
            raise ValueError("Units must match for addition")
        return Memory(amount=self.amount + other.amount, unit=self.unit)

    def __sub__(self, other: 'Memory') -> 'Memory':
        # 示例减法逻辑:需保证单位一致
        if self.unit != other.unit:
            raise ValueError("Units must match for subtraction")
        return Memory(amount=self.amount - other.amount, unit=self.unit)

    def __mul__(self, other: int) -> 'Memory':
        # 示例乘法逻辑
        return Memory(amount=self.amount * other, unit=self.unit)

    # 重载场景1:Memory 除以 Memory,返回比例值float
    @overload
    def __truediv__(self, other: 'Memory') -> float:
        ...

    # 重载场景2:Memory 除以 int,返回拆分后的Memory实例
    @overload
    def __truediv__(self, other: int) -> 'Memory':
        ...

    # 实际实现除法逻辑,处理两种输入类型
    def __truediv__(self, other: Union['Memory', int]) -> Union['Memory', float]:
        if isinstance(other, Memory):
            if self.unit != other.unit:
                # 实际项目中可添加单位转换逻辑,示例简化为抛出异常
                raise ValueError("Units must match for ratio calculation")
            return self.amount / other.amount
        elif isinstance(other, int):
            # 这里根据需求选择浮点除法或整数除法,示例用整数除法
            return Memory(amount=self.amount // other, unit=self.unit)
        else:
            raise TypeError(f"Unsupported division with type: {type(other)}")

关键说明

  • Mypy会根据调用时传入的参数类型,自动匹配对应的重载签名,正确推断返回类型:
    mem1 = Memory(amount=10, unit=MemoryUnit.GB)
    mem2 = Memory(amount=5, unit=MemoryUnit.GB)
    
    ratio = mem1 / mem2  # Mypy会推断ratio为float类型
    split_mem = mem1 / 2  # Mypy会推断split_mem为Memory类型
    
  • 实际实现中记得处理单位不匹配的情况,比如两个Memory实例单位不同时,可添加单位转换逻辑(比如把GB转TB后再计算),避免直接抛出异常。

内容的提问来源于stack exchange,提问作者zefciu

火山引擎 最新活动