Супер ленивое (и, вероятно, неправильное) решение:
Вместо того, чтобы добавлять конкретное значение, класс int
может быть расширен путем создания подклассов. Этот подход не лишен ряда ловушек и проблем, таких как требование обрабатывать значение бесконечности для различных __dunder__
методов (т.е. __add__
, __mul__
, __eq__
и т.п., и все они должны быть протестированы). Это было бы неприемлемым объемом накладных расходов в случаях использования, когда требуется конкретное значение. В таком случае упаковка желаемого значения с помощью typing.cast
будет иметь возможность лучше указать системе подсказок типов, какое конкретное значение (например, inf = cast(int, math.inf)
) приемлемо для присвоения.
Причина, по которой этот подход неверен, проста в следующем: поскольку назначенное значение выглядит / ощущается как некоторое число, некоторые другие пользователи вашего API могут случайно использовать это как int
, и тогда программа может сильно взорваться, когда math.inf
( или их вариации).
Аналогия заключается в следующем: учитывая, что в списках есть элементы, индексированные положительными целыми числами, мы ожидаем, что любая функция, возвращающая индекс для некоторого элемента, будет некоторым положительным целым числом, поэтому мы можем использовать его напрямую (я знаю, что это не так в Python учитывая, что есть семантика, которая позволяет использовать отрицательные значения индекса, но представьте, что мы работаем, скажем, с C на данный момент). Скажем, эта функция возвращает первое вхождение совпадающего элемента, но если есть какие-либо ошибки, она возвращает некоторое отрицательное число, которое явно превышает диапазон допустимых значений для индекса для некоторого элемента. Отсутствие защиты от наивного использования возвращаемого значения неизбежно приведет к проблемам, которые должна решать система типов.
По сути, создание суррогатных значений и отметка их как int
будет предлагать нулевое значение и неизбежно позволит автоматически проявить неожиданные и неработающие API / поведение программы из-за неправильного использования.
Не говоря уже о том, что бесконечность не является числом, поэтому никакое значение int
не может правильно представляют это (учитывая, что int
по самой своей природе представляют некоторое конечное число).
В качестве альтернативы, посмотрите str.index
vs _ 14_. Один из них имеет возвращаемое значение, которое определенно нарушает ожидания пользователя (т.е. превышает границы типа положительное целое число; не будет сказано, что возвращаемое значение может быть недопустимым для контекста, в котором оно может использоваться во время компиляции, приводит к потенциальный отказ случайным образом во время выполнения).
Формулировка вопроса / ответа в более правильных терминах:
Учитывая, что проблема действительно связана с присвоением некоторого целого числа при наличии скорости, и если таковой не существует, следует использовать какой-либо другой токен, который представляет неограниченность для конкретного варианта использования (это может быть какое-то встроенное значение, такое как NotImplemented
или None
). Однако, поскольку эти токены также не будут int
значениями, это означает, что myvar
действительно потребуется тип, который их охватывает, и способ применения операции, которая будет делать правильные вещи.
К сожалению, это не очень хорошо доступно напрямую в Python, однако в языках со строго статической типизацией, таких как Haskell, более приемлемым решением является использование _ 19_ для определения типа числовой тип, допускающий бесконечность. Обратите внимание, что хотя там также доступна бесконечность с плавающей запятой, она наследует все проблемы чисел с плавающей запятой, что делает это несостоятельным решением (опять же, не используйте для этого inf
).
Вернемся к Python: в зависимости от свойства назначения, которое вы действительно хотите, это может быть так же просто, как создание класса с конструктором, который может принимать int
или None
(или NotImplemented
), а затем предоставить метод, который пользователи класс может использовать фактическое значение. К сожалению, Python не предоставляет расширенные конструкции, чтобы сделать это элегантным, поэтому вы неизбежно получите код, управляющий этим, будет разбрызгиваться повсюду, или вам придется написать ряд методов, которые обрабатывают любой ввод, как ожидалось, и производят требуемый вывод в конкретными способами, которые актуальны для вашей программы.
К сожалению, подсказка типов на самом деле только царапает поверхность и просто перебирает то, что более продвинутые языки предоставили и решили на более фундаментальном уровне. Я предположил, что если нужно программировать на Python, это лучше, чем не иметь его.
person
metatoaster
schedule
24.02.2019
int
. Если не осторожно, то легко сломать вещи. И не стоит рисковать. И чтобы ответить на вопрос, что и почему: я имею дело с ограничениями скорости сервисных маршрутизаторов. Они указываются в кбит / с (целое число). Но они также могут быть неограниченными (что соответствует бесконечному пределу). - person exhuma   schedule 20.02.2019inf = cast(int, math.inf)
, а затем начать везде использовать вашу пользовательскую константуinf
вместоmath.inf
. Однако я согласен с анализом @metatoaster здесь: я думаю, что все решения, которые он или она обсуждали, более чистые и надежные, чем то, что я представил. - person Michael0x2a   schedule 22.02.2019