Ответ 1
Итак, вы думаете, что можете dance с плавающей запятой?
123
- это такая же часть объекта, как 3.14
, "проблема" лежит в грамматических правилах языка; парсер думает, что мы собираемся определить float — не int с обратным вызовом метода.
Мы получим ожидаемое поведение, если обернуть число в скобках, как показано ниже.
>>> (123).__str__()
'123'
Или если мы просто добавим пробелы после 123
:
>>> 123 .__str__()
'123'
Причина, по которой она не работает для 123.__str__()
, заключается в том, что точка, следующая за 123
, интерпретируется как десятичная точка некоторой частично объявленной плавающей запятой.
>>> 123.__str__()
File "", line 1
123.__str__()
^
SyntaxError: invalid syntax
Парсер пытается интерпретировать __str__()
как последовательность цифр, но, очевидно, не работает — и мы получаем SyntaxError, в основном говорящий, что парсер наткнулся на то, чего он не ожидал.
Разработка
При просмотре 123.__str__()
анализатор python может использовать либо 3 символа и интерпретировать эти 3 символа как целое число, или, он может использовать 4 символа и интерпретировать их как start с плавающей запятой.
123.__str__()
^^^ - int
123.__str__()
^^^^- start of floating-point
Так же, как маленький ребенок хотел бы как можно больше пирога на своей тарелке, парсер жадный и хотел бы усвоить столько, сколько он может все сразу; даже если это не всегда лучшая из идей, так как выбрана последняя ( "лучшая" ) альтернатива.
Когда он позже понимает, что __str__()
никоим образом не может быть интерпретирован как десятичные числа с плавающей запятой, уже слишком поздно; SyntaxError.
Примечание
123 .__str__() # works fine
В приведенном выше фрагменте
123
(обратите внимание на пробел) необходимо интерпретировать как целое число, поскольку число не может содержать пробелы. Это означает, что он семантически эквивалентен(123).__str__()
.
Примечание
123..__str__() # works fine
Вышеупомянутое также работает, потому что число может содержать не более одной десятичной точки, что означает, что оно эквивалентно
(123.).__str__()
.
Для юристов-языковедов
Этот раздел содержит лексическое определение соответствующих литералов.
Лексический анализ - 2.4.5 Литералы с плавающей точкой
floatnumber ::= pointfloat | exponentfloat
pointfloat ::= [intpart] fraction | intpart "."
exponentfloat ::= (intpart | pointfloat) exponent
intpart ::= digit+
fraction ::= "." digit+
exponent ::= ("e" | "E") ["+" | "-"] digit+
Лексический анализ - 2.4.4 Целочисленные литералы
integer ::= decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::= nonzerodigit digit* | "0"+
nonzerodigit ::= "1"..."9"
digit ::= "0"..."9"
octinteger ::= "0" ("o" | "O") octdigit+
hexinteger ::= "0" ("x" | "X") hexdigit+
bininteger ::= "0" ("b" | "B") bindigit+
octdigit ::= "0"..."7"
hexdigit ::= digit | "a"..."f" | "A"..."F"
bindigit ::= "0" | "1"