Супер-ленивое (и, вероятно, неправильное) решение:
Вместо добавления определенного значения класс int
можно расширить с помощью подклассов.Этот подход не обходится без ряда подводных камней и проблем, таких как требование обрабатывать значение бесконечности для различных методов __dunder__
(то есть __add__
, __mul__
, __eq__
и т. П., И все они должныбыть проверенным).Это было бы недопустимым количеством накладных расходов в тех случаях, когда требуется конкретное значение.В таком случае перенос нужного значения с помощью typing.cast
сможет лучше указать системе подсказок типа, что конкретное значение (т. Е. inf = cast(int, math.inf)
) будет приемлемым для присвоения.
Причина, по которой этот подход неверен, заключается просто в следующем: поскольку назначенное значение выглядит / ощущается точно как некоторое число, некоторые другие пользователи вашего API могут в конечном итоге непреднамеренно использовать его как int
, и тогда программа может взорваться, когдаmath.inf
(или варианты такого рода).
Аналогия такова: учитывая, что списки имеют элементы, которые проиндексированы с помощью положительных целых чисел, мы ожидаем, что любая функция, которая возвращает индекс для некоторого элемента, будет некоторойположительное целое число, поэтому мы можем использовать его напрямую (я знаю, что в Python это не так, поскольку есть семантика, позволяющая использовать отрицательные значения индекса, но представьте, что мы сейчас работаем с, скажем, C).Скажем, эта функция возвращает первое вхождение соответствующего элемента, но при наличии ошибок возвращает некоторое отрицательное число, которое явно превышает диапазон допустимых значений индекса для некоторого элемента.Это отсутствие защиты от наивного использования возвращаемого значения неизбежно приведет к проблемам, которые должна решить система типов.
По сути, создание суррогатных значений и маркировка, что int
будет предлагать нулевое значение,и неизбежно позволять программе автоматически разрешать непредвиденное и неработающее API / поведение из-за неправильного использования.
Не говоря уже о том, что бесконечность не является числом , следовательно, нет *Значение 1025 * может правильно представлять это (учитывая, что int
представляет некоторое конечное число по самой своей природе).
В качестве отступления, посмотрите str.index
против str.find
.У одного из них есть возвращаемое значение, которое определенно нарушает ожидания пользователя (т. Е. Выходит за границы положительного целого числа типа; не будет сказано, что возвращаемое значение может быть недопустимым для контекста, в котором оно может использоваться во время компиляции, что приводит кпотенциальный сбой случайным образом во время выполнения).
Обрамление вопроса / ответа в более правильных терминах:
Учитывая, что проблема действительно в назначении некоторого целого числа, когда существует ставка, и, если ее нет, некоторыедолжен быть создан другой токен, который представляет неограниченность для конкретного варианта использования (это может быть некоторое встроенное значение, такое как NotImplemented
или None
).Однако, поскольку эти токены также не будут иметь значения int
, это означает, что myvar
на самом деле потребуется тип, который включает их, и способ применения операции, которая будет делать правильные вещи.
К сожалению, это не так.Непосредственно доступны в Python очень хорошим способом, однако в строго статических типизированных языках, таких как Haskell, более приемлемым решением является использование типа Maybe
для определения числового типа , который может приниматьбесконечность .Обратите внимание, что, хотя бесконечность с плавающей запятой также доступна там, она наследует все проблемы чисел с плавающей запятой, что делает это несостоятельным решением (опять же, не используйте для этого inf
).
Возвращаясь к Python: в зависимости от свойства присваивания, которое вы на самом деле хотите, это может быть так же просто, как создать класс с конструктором, который может принимать int
или None
(или NotImplemented
), изатем предоставьте метод, который пользователи класса могут использовать фактическое значение.К сожалению, Python не предоставляет продвинутых конструкций, чтобы сделать это элегантно, так что вы неизбежно получите код, управляющий этим, будет разбросан повсюду, или вам придется написать несколько методов, которые обрабатывают любой ввод, как ожидается, и производят требуемый вывод вконкретные способы, которые действительно нужны вашей программе.
К сожалению, намеки на типы на самом деле только поверхностно отражаются на том, что предлагали и решали более продвинутые языки на более фундаментальном уровне.Я предположил, что если нужно программировать на Python, это лучше, чем не иметь его.