弑天下
理论上,您可以通过制作一个通用协议来完成他的一部分first,它可以让您“捕获” __add__. 例如:# If you are using Python 3.7 or earlier, you'll need to pip-install# the typing_extensions module and import Protocol from there.from typing import TypeVar, Protocol, GenericTOther = TypeVar('TOther', contravariant=True)TSum = TypeVar('TSum', covariant=True)class SupportsAdd(Protocol, Generic[TOther, TSum]): def __add__(self, other: TOther) -> TSum: ...然后,您可以执行以下操作:S = TypeVar('S')R = TypeVar('R')# Due to how we defined the protocol, R will correspond to the# return type of `__add__`.def sum_two(first: SupportsAdd[S, R], second: S) -> R: return first + second# Type checksreveal_type(sum_two("foo", "bar")) # Revealed type is strreveal_type(sum_two(1, 2)) # Revealed type is intreveal_type(sum_two(1.0, 2)) # Revealed type is float# Does not type check, since float's __radd__ is ignoredsum_two(1, 2.0)class Custom: def __add__(self, x: int) -> int: return x# Type checksreveal_type(sum_two(Custom(), 3)) # Revealed type is int# Does not type checkreveal_type(sum_two(Custom(), "bad"))但是,这种方法确实有一些限制:它不处理__add__在“第一”中没有匹配但__radd__在“第二”中有匹配的情况。如果你修改自定义,你可能会得到一些奇怪的结果,所以这__add__是一个重载。我认为至少 mypy 目前有一个错误,它不知道如何正确处理涉及子类型和重载的复杂情况。