Как обрабатывать ведущие нули в числовом поле?
Что проверяют
Понимаете ли вы, что поле с ведущими нулями почти всегда не число, а идентификатор: почтовый индекс, артикул, номер счёта, код подразделения. Следом спрашивают, как хранить такое поле в базе и где нули теряются незаметно.
Как отвечать
Первый вопрос к полю: вы с ним что-то считаете? Если нет, это строка, и валидировать её нужно как строку:
- проверка формата:
re.fullmatch(r"[0-9]{6}", value). Именно[0-9], а не\d: в Python\dпо умолчанию совпадает с любыми цифрами Юникода, включая арабские; - Pydantic: поле типа
strс ограничениемpattern, напримерAnnotated[str, StringConstraints(pattern=...)]. Если объявитьint, в обычном режиме"00123"молча станет123; - Django:
CharFieldсRegexValidator, а неIntegerField; - база:
VARCHARилиTEXT, иначе нули пропадут при записи.
Если поле действительно числовое, а нули пришли от ввода или экспорта, int("00123") вернёт 123, это нормальное поведение. Обратно дополнить нулями можно через str(n).zfill(6) или f"{n:06d}".
Полезно знать особенности int(): он принимает пробелы по краям, подчёркивания (int("1_000") даёт 1000) и цифры других алфавитов. А литерал 007 в исходном коде Python 3 это SyntaxError, восьмеричные числа пишутся как 0o7. Вызов int(value, 0) определяет систему счисления по префиксу и строку "010" отвергает.
Отдельная зона риска это загрузка данных. pandas.read_csv превратит колонку индексов в int64, поэтому нужен dtype={"zip": str}. В JSON число с ведущим нулём по стандарту недопустимо, такие значения передают строкой.
Где спотыкаются
Приводят идентификатор к int «для надёжности». Индекс 012345 становится 12345, и если длина кода не фиксирована, исходное значение уже не восстановить.
Проверяют ввод через str.isdigit(). Метод вернёт True для надстрочной ², а int("²") упадёт с ValueError; точнее isdecimal() или регулярное выражение с [0-9].
Думают только о своём коде и забывают про цепочку: Excel при открытии CSV, промежуточный скрипт на pandas, колонка INTEGER в базе. Нули теряются на любом шаге, и искать потерю приходится по всей цепочке.