На питання вже досить відповіді (тобто відповідь @Paul Rooney ), але також можна перевірити правильність цих відповідей.
Дозвольте мені резюмувати наявні відповіді: The ..
- це не один елемент синтаксису!
Ви можете перевірити, як "токенізований" вихідний код . Ці лексеми представляють, як інтерпретується код:
>>> 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.
інтерпретується як число, другий .
- це ОП (оператор, в даному випадку оператор "отримати атрибут"), а " __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__
(з пробілом) `