Контринтуитивное поведение int() в python

В docs четко указано, что int (number) является преобразованием типа пола:

int(1.23)
1

и int (string) возвращает int тогда и только тогда, когда строка является целым литералом.

int('1.23')
ValueError

int('1')
1

Есть ли какая-то особая причина для этого? Мне кажется противоречивым, что функция поэта в одном случае, но не в другом.

Ответ 1

Нет особой причины. Python просто применяет свой общий принцип невыполнения неявных преобразований, которые являются известными причинами проблем, особенно для новичков, на таких языках, как Perl и Javascript.

int(some_string) - явный запрос на преобразование строки в целочисленный формат; правила для этого преобразования указывают, что строка должна содержать допустимое целочисленное литеральное представление. int(float) - явный запрос для преобразования float в целое число; правила для этого преобразования указывают, что дробная часть с плавающей запятой будет усечена.

Для возврата int("3.1459") 3 интерпретатор должен будет неявно преобразовать строку в float. Поскольку Python не поддерживает неявные преобразования, он выбирает вместо этого исключение.

Ответ 2

Это почти наверняка относится к применению трех принципов из Zen of Python:

Явный лучше неявный.

[...] практичность превосходит чистоту

Ошибки никогда не должны проходить молча

Некоторое количество времени, когда кто-то делает int('1.23'), вызывает неправильное преобразование для своего варианта использования и вместо этого хочет что-то вроде float или decimal.Decimal. В этих случаях им явно лучше получить немедленную ошибку, которую они могут исправить, вместо того, чтобы молча дать неправильное значение.

В том случае, если вы хотите усечь это для int, тривиально явно сделать это, сначала передав его через float, а затем вызвав один из int, round, trunc, floor или ceil. Это также делает ваш код более самодокументированным, защищая от более поздней модификации "исправление" гипотетического молчащего усечения int вызова float, давая понять, что округленное значение - это то, что вы хотите.

Ответ 3

Иногда может быть полезен мысленный эксперимент.

  • Поведение A: int('1.23') завершается с ошибкой. Это существующее поведение.
  • Поведение B: int('1.23') создает 1 без ошибок. Это то, что вы предлагаете.

С поведением A это просто и тривиально, чтобы получить эффект поведения B: вместо этого используйте int(float('1.23')).

С другой стороны, с поведением B получение эффекта поведения A значительно сложнее:

def parse_pure_int(s):
    if "." in s:
        raise ValueError("invalid literal for integer with base 10: " + s)
    return int(s)

(и даже с приведенным выше кодом, у меня нет полной уверенности в том, что нет какого-либо углового случая, который он неправильно понимает.)

Поведение A поэтому более выразительно, чем поведение B.

Другое дело: '1.23' - строковое представление значения с плавающей запятой. Преобразование '1.23' в целое понятие концептуально включает в себя два преобразования (строка для float to integer), но int(1.23) и int('1') содержат только одно преобразование.


Edit:

И действительно, есть угловые случаи, в которых вышеприведенный код не обрабатывал: 1e-2 и 1e-2 тоже являются значениями с плавающей запятой.

Ответ 4

Простыми словами - это не одна и та же функция.

  • int (десятичный) ведет себя как "пол, то есть сбивает десятичную часть и возвращает как int"
  • int (string) ведет себя как "этот текст описывает целое число, преобразует его и возвращает как int".

Это две разные функции с тем же именем, которые возвращают целое число, но они разные.

'int' коротко и легко запоминается, и его значение, применяемое к каждому типу, интуитивно для большинства программистов, поэтому они его выбрали.

Там не подразумевается, что они предоставляют одинаковые или комбинированные функции, они просто имеют одно и то же имя и возвращают один и тот же тип. Их можно было бы легко назвать "floorDecimalAsInt" и "convertStringToInt", но они пошли на "int", потому что легко запомнить (99%) интуитивно понятный и путаный процесс редко встречался.

Анализ текста в виде целых чисел для текста, который включает десятичную точку, например "4.5", выдает ошибку на большинстве языков компьютера и, как ожидается, будет вызывать ошибку большинством программистов, поскольку текстовое значение не представляет собой целое число и подразумевает, что они предоставляют ошибочные данные