Почему Python не требует пробелов вокруг ключевых слов?

Почему пробелы иногда могут быть опущены до и после ключевых слов? Например, почему выражение 2if-1e1else 1 valid?

Кажется, работает как в CPython 2.7, так и в версии 3.3:

$ python2
Python 2.7.3 (default, Nov 12 2012, 09:50:25) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 2if-1e1else 1
2

$ python3
Python 3.3.0 (default, Nov 12 2012, 10:01:55) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 2if-1e1else 1
2

и даже в PyPy:

$ pypy
Python 2.7.2 (341e1e3821ff, Jun 07 2012, 15:42:54)
[PyPy 1.9.0 with GCC 4.2.1] on darwin
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``PyPy 1.6 released!''
>>>> 2if-1e1else 1
2

Ответы

Ответ 1

Идентификаторы в python описываются как:

identifier ::= (letter|"_") (letter | digit | "_")* 

Следовательно, 2if не может быть идентификатором, следовательно, если должно быть 2, if. Аналогичная логика применяется к остальной части выражения.

В основном интерпретация 2if-1e1else 1 будет выглядеть примерно так (полный анализ будет довольно сложным):

2if Недействительный идентификатор, 2 соответствует значению digit ::= "0"..."9", if соответствует ключевому слову. -1e1else, -1 - это унарное отрицание (u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr) : (1, которое соответствует intpart в exponentfloat ::= (intpart | pointfloat) | exponent  , e1 является экспонентой exponent ::= ("e" | "E") ["+" | "-"] digit+.) Вы можете видеть, что выражения формы Ne+|-x дают поплавок из:

>>> type(2e3)
<type 'float'>

тогда else рассматривается как ключевое слово, а -1 и т.д.

Вы можете прочитать гаммар, чтобы узнать больше об этом.