Почему 1.__ добавить __ (2) не получается?

Возможный дубликат:
доступ к методам литералов int python

В Python everything is an object.

Но опять же, почему не работает следующий фрагмент?

1.__add__(2)

Однако это работает:

n = 1
n.__add__(2)

В чем разница между n и 1?

Разве это не сбой дизайна, что он не работает? Например, он работает с литералами string.

"one".__add__("two")

Для сравнения, он хорошо работает и на других чисто объектно-ориентированных языках.

Давайте более подробно рассмотрим этот пример компиляции С#:

Console.WriteLine(100.ToString());

И снова, что отличает Python от C# в перспективе everything is an object?

Ответы

Ответ 1

Парсер Python преднамеренно очень прост - одно из ограничений, которое оно налагает на себя, заключается в том, что, чтобы понять, что означает токен, он может только смотреть на один токен справа (это LL (1) парсер).

Итак, он видит [число] [точка] и определяет, что это литерал с плавающей запятой. '_' не является допустимым символом, который должен иметь в литерале с плавающей точкой, поэтому он дает синтаксическую ошибку.

Наиболее очевидным и наиболее распространенным способом преодоления этого является помещение числа в круглые скобки:

(1).__add__(2)

Это заставляет его интерпретировать 1 как целочисленный литерал и точку как доступ к атрибуту в пределах ограничений синтаксического анализатора.

Еще одно интересное обходное решение:

>>> 1 .__add__(2) 
3

То есть, добавьте пробел перед .. Оказывается, Python всегда позволяет найти место для поиска любого атрибута:

>>> range(4) .count(3)
1

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

Ответ 2

Python интерпретирует 1. как float, поэтому вам нужно добавить parens:

>>> (1).__add__(2)
3

или пробел:

>>> 1 .__add__(2)
3

Если вы хотите, чтобы значение float здесь просто помещало 2 точки.

>>> 1..__add__(2) #float
3.0