Die Frage ist bereits ausreichend beantwortet (dh die Antwort von @Paul Rooney ), es ist jedoch auch möglich, die Richtigkeit dieser Antworten zu überprüfen.
Lassen Sie mich die vorhandenen Antworten zusammenfassen: Das ..
ist kein einzelnes Syntaxelement!
Sie können überprüfen, wie der Quellcode "tokenisiert" ist . Diese Token stellen dar, wie der Code interpretiert wird:
>>> 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__'),
...]
Die Zeichenfolge 1.
wird also als Zahl interpretiert, die zweite .
ist ein OP (ein Operator, in diesem Fall der Operator "get attribute") und __truediv__
der Methodenname. Dies ist also nur ein Zugriff auf die __truediv__
Methode des Floats 1.0
.
Eine andere Möglichkeit, den generierten Bytecode anzuzeigen, besteht darin , ihn zusammenzusetzen. Dies zeigt tatsächlich die Anweisungen, die ausgeführt werden, wenn Code ausgeführt wird: 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
Was im Grunde das gleiche sagt. Es lädt das Attribut __truediv__
der Konstante 1.0
.
Was Ihre Frage betrifft
Und wie können Sie es in einer komplexeren Aussage verwenden (wenn möglich)?
Auch wenn es möglich ist, dass Sie niemals solchen Code schreiben sollten, einfach weil unklar ist, was der Code tut. Verwenden Sie es also bitte nicht in komplexeren Aussagen. Ich würde sogar so weit gehen, dass Sie es nicht in so "einfachen" Anweisungen verwenden sollten, zumindest sollten Sie die Anweisungen in Klammern trennen:
f = (1.).__truediv__
dies wäre definitiv besser lesbar - aber etwas in der Art von:
from functools import partial
from operator import truediv
f = partial(truediv, 1.0)
wäre noch besser!
Der verwendete Ansatz partial
bewahrt auch das Python-Datenmodell (der 1..__truediv__
Ansatz nicht!), Was durch dieses kleine Snippet demonstriert werden kann:
>>> 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
Dies liegt daran, dass 1. / (1+2j)
nicht von, float.__truediv__
sondern mit complex.__rtruediv__
- ausgewertet wird , um operator.truediv
sicherzustellen, dass die umgekehrte Operation aufgerufen wird, wenn die normale Operation zurückkehrt, NotImplemented
aber Sie diese Fallbacks nicht haben, wenn Sie __truediv__
direkt arbeiten. Dieser Verlust des "erwarteten Verhaltens" ist der Hauptgrund, warum Sie (normalerweise) magische Methoden nicht direkt anwenden sollten.
(1).__truediv__
ist nicht wirklich dasselbe wie1..__truediv__
, wie der erstere anruft,int.__truediv__
während der letztere es tutfloat.__truediv__
. Alternativ können Sie auch1 .__truediv__
(mit einem Leerzeichen) `