Как проверить, что входные значения являются числовыми в Python?
Что проверяют
Знаете ли вы, что «число» в Python понятие неоднозначное: тип значения, строка из формы, bool, Decimal, NaN. Сначала интервьюер хочет услышать уточнение: проверяем тип объекта или то, можно ли превратить ввод в число. Следом обычно спрашивают, что ваша функция скажет про True и строку "nan".
Как отвечать
Разведите два случая. Первый: проверка типа. Идиоматично через абстрактные классы из модуля numbers:
from numbers import Real
def is_number(x): return isinstance(x, Real) and not isinstance(x, bool)bool: наследникint, поэтомуisinstance(True, int)даётTrue. Если флаг не должен проходить как число, исключайте его явно;numbers.Real: пропускаетint,float,Fraction, но неDecimalи неcomplex. ЕслиDecimalнужен, проверяйтеnumbers.Numberили добавьте его отдельно;- конечность:
float('nan')иfloat('inf')тожеfloat, для них нуженmath.isfinite.
Второй случай: строка из ввода. Здесь работает принцип «проще попросить прощения»: пытаетесь преобразовать и ловите исключение.
float(s)вtry/except (ValueError, TypeError): принимает пробелы по краям, экспоненту1e3, подчёркивания1_000, а также"nan"и"inf", поэтому после преобразования снова нуженmath.isfinite;str.isdigit(): не годится как универсальный ответ. Минус и точку он не пропускает, а надстрочную"²"считает цифрой, хотяint("²")падает;- целое: если нужно именно целое, пробуйте
int(s), а неfloat, иначе"1.5"пройдёт.
В реальном сервисе ручные проверки обычно заменяет схема: pydantic в FastAPI сама приводит и валидирует поля, а строгий режим запрещает неявное превращение строки в число.
Где спотыкаются
Проверяют isinstance(x, int) и не замечают, что True проходит как единица.
Считают, что успешный float(x) означает «нормальное число», и пропускают NaN и бесконечность, которые потом ломают сортировку и суммы.
Ставят голый except: вокруг преобразования. Он глотает всё, вплоть до KeyboardInterrupt, и прячет настоящие ошибки.