Я считаю, что проблема здесь не столько в том, что вы используете SupportsRound
, сколько в определении функции round
. Функция round
определена в typeshed, репозитории подсказок типов для стандартной библиотеки, чтобы иметь следующая подпись:
@overload
def round(number: float) -> int: ...
@overload
def round(number: float, ndigits: None) -> int: ...
@overload
def round(number: float, ndigits: int) -> float: ...
@overload
def round(number: SupportsRound[_T]) -> int: ...
@overload
def round(number: SupportsRound[_T], ndigits: None) -> int: ... # type: ignore
@overload
def round(number: SupportsRound[_T], ndigits: int) -> _T: ...
Обратите внимание: если указан только один аргумент или ndigits
имеет значение None, на выходе всегда будет int
. Это соответствует документированному поведению функции round
в стандартной библиотеке: https://docs.python.org/3/library/functions.html#round
К сожалению, я не вижу действительно чистого способа обойти это: я не думаю, что реализация SupportsRound действительно соответствует этому поведению.
В частности, SupportsRound, вероятно, следовало определить примерно так:
@runtime
class SupportsRound(Protocol[_T_co]):
@abstractmethod
@overload
def __round__(self, ndigits: None = None) -> int: ...
@abstractmethod
@overload
def __round__(self, ndigits: int) -> _T_co: ...
По сути, вынуждайте пользователя обрабатывать эти два случая.
На самом деле изменение определения, вероятно, было бы сложным: на самом деле нет чистого способа обновления любых старых версий Python, которые поставляются в комплекте со старыми версиями модуля набора текста.
Я бы порекомендовал зарегистрировать проблему по этому поводу в системе отслеживания проблем. Я лично думаю, что вы обнаружили здесь настоящую несоответствие / ошибку, но, возможно, здесь есть какой-то нюанс, который мне не хватает, поэтому я думаю, что было бы хорошо обострить это.
person
Michael0x2a
schedule
27.11.2018