Доступ к атрибутам на литералах работает на всех типах, но не `int`; почему?


Я читал, что все в Python является объектом, и поэтому я начал экспериментировать с различными типами и вызов __str__ на них - сначала я был очень взволнован, но потом я запутался.

>>> "hello world".__str__()
'hello world'
>>> [].__str__()
'[]'
>>> 3.14.__str__()
'3.14'
>>> 3..__str__()
'3.0'
>>> 123.__str__()
  File "<stdin>", line 1
    123.__str__()
              ^
SyntaxError: invalid syntax
  • почему something.__str__() работать на "все", кроме int?
  • и 123 не объект типа int?
4   51   2015-10-10 15:55:24

4 ответа:

нужно скобки:

(4).__str__()

проблема в том, что лексер думает " 4."это будет число с плавающей точкой.

кроме того, это работает:

x = 4
x.__str__()

вы можете найти танец с плавающей точкой?

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 символы и интерпретировать их как старт в с плавающей точкой.

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"

добавить пробел после 4:

4 .__str__()

в противном случае лексер разделит это выражение на токены "4.","__str__","(" и ")", т. е. первый знак интерпретируется как число с плавающей точкой. Лексер всегда пытается построить максимально длинный токен.

на самом деле (для повышения нечитаемости...):

4..hex()

действительно, слишком. это дает '0x1.0000000000000p+2' -- но тогда это поплавок, конечно...