На вопрос уже получен достаточный ответ (т. Е. Ответ Пола Руни ), но также можно проверить правильность этих ответов.
Позвольте мне повторить существующие ответы: Это ..
не единственный элемент синтаксиса!
Вы можете проверить, как исходный код «токенизируется» . Эти токены представляют, как код интерпретируется:
>>> from tokenize import tokenize
>>> from io import BytesIO
>>> s = "1..__truediv__"
>>> list(tokenize(BytesIO(s.encode('utf-8')).readline))
[...
TokenInfo(type=2 (NUMBER), string='1.', start=(1, 0), end=(1, 2), line='1..__truediv__'),
TokenInfo(type=53 (OP), string='.', start=(1, 2), end=(1, 3), line='1..__truediv__'),
TokenInfo(type=1 (NAME), string='__truediv__', start=(1, 3), end=(1, 14), line='1..__truediv__'),
...]
Таким образом, строка 1.
интерпретируется как число, вторым .
является OP (оператор, в данном случае оператор «get attribute»), а __truediv__
это имя метода. Так что это просто доступ к __truediv__
методу поплавка 1.0
.
Другой способ просмотра сгенерированного байт-кода заключается в его сборке . Это фактически показывает инструкции, которые выполняются, когда выполняется некоторый код: dis
>>> import dis
>>> def f():
... return 1..__truediv__
>>> dis.dis(f)
4 0 LOAD_CONST 1 (1.0)
3 LOAD_ATTR 0 (__truediv__)
6 RETURN_VALUE
Который в основном говорит то же самое. Загружает атрибут __truediv__
константы 1.0
.
По вашему вопросу
И как вы можете использовать его в более сложном утверждении (если это возможно)?
Хотя возможно, что вы никогда не должны писать такой код просто потому, что неясно, что делает код. Поэтому, пожалуйста, не используйте его в более сложных утверждениях. Я бы даже зашел так далеко, что вы не должны использовать его в таких «простых» выражениях, по крайней мере, вы должны использовать скобки для разделения инструкций:
f = (1.).__truediv__
это было бы определенно более читабельно - но что-то вроде:
from functools import partial
from operator import truediv
f = partial(truediv, 1.0)
было бы еще лучше!
Подход, использующий подход, partial
также сохраняет модель данных Python ( 1..__truediv__
подход не делает!), Что можно продемонстрировать с помощью этого небольшого фрагмента:
>>> f1 = 1..__truediv__
>>> f2 = partial(truediv, 1.)
>>> f2(1+2j) # reciprocal of complex number - works
(0.2-0.4j)
>>> f2('a') # reciprocal of string should raise an exception
TypeError: unsupported operand type(s) for /: 'float' and 'str'
>>> f1(1+2j) # reciprocal of complex number - works but gives an unexpected result
NotImplemented
>>> f1('a') # reciprocal of string should raise an exception but it doesn't
NotImplemented
Это потому, что 1. / (1+2j)
не оценивается, float.__truediv__
а с complex.__rtruediv__
- operator.truediv
гарантирует, что обратная операция вызывается, когда нормальная операция возвращается, NotImplemented
но у вас нет этих откатов, когда вы работаете __truediv__
напрямую. Эта потеря «ожидаемого поведения» является основной причиной, по которой вы (обычно) не должны использовать магические методы напрямую.
(1).__truediv__
самом деле это не то же самое1..__truediv__
, что первый вызов, вint.__truediv__
то время как последний делаетfloat.__truediv__
. Кроме того, вы также можете использовать1 .__truediv__
(с пробелом) `