Qu'est - `1..__truediv__` ? Python ont une .. (“dot dot”) de la notation de syntaxe?
Je suis récemment tombé sur une syntaxe je n'ai jamais vu avant, quand j'ai appris le python, ni dans la plupart des tutoriels, de la ..
notation, il ressemble à quelque chose comme ceci:
f = 1..__truediv__ # or 1..__div__ for python 2
print(f(8)) # prints 0.125
J'ai pensé que c'était exactement la même chose que (sauf que c'est plus, bien sûr):
f = lambda x: (1).__truediv__(x)
print(f(8)) # prints 0.125 or 1//8
Mais mes questions sont:
- Comment peut-il le faire?
- Qu'est-ce que ça veux dire avec les deux points?
- Comment pouvez-vous l'utiliser dans un environnement plus complexe déclaration (si possible)?
Cela va probablement me sauver de nombreuses lignes de code dans le futur...:)
- Remarque:
(1).__truediv__
n'est pas vraiment la même chose que1..__truediv__
, comme l'ancien appelsint.__truediv__
tandis que les seconds nefloat.__truediv__
. Alternativement, vous pouvez également utiliser1 .__truediv__
(avec un espace)` - Notez que
1//8
est0
, pas0.125
, dans les deux versions de Python. - me rappelle de
if (x <- 3) {...}
- Ici est un exemple de cette utilisation.
- Si vous allez écrire un lambda, écrire
lambda x: 1/x
, qui est un caractère plus courte (de la même longueur si vous avez besoin d'1./x
) Tout ce qui implique d'appeler explicitement un__method__
(en dehors d'une classe dérivée première d'une telle méthode) probablement tombe dans la catégorie "stupide python astuces" - le plaisir de la raison, mais presque certainement n'a pas sa place dans le code de production. - S'il vous plaît pouvez-vous donner une explication avec votre commentaire, donc les raisons pour lesquelles ce ne devrait pas être fait compréhensibles?
- La haute qualité des réponses et des commentaires montrent l'exemple de code des besoins de perspicacité pour comprendre, est surprenant pour beaucoup, a des alternatives qui sont plus clairs, plus générale, et au moins aussi efficace. Mon principal reproche est que la lisibilité compte. Enregistrer l'intelligence de l'endroit où il est le plus nécessaire - communiquer avec les humains.
Vous devez vous connecter pour publier un commentaire.
Ce que vous avez est un
float
littérale sans le dernier zéro, que vous pouvez ensuite accéder à la__truediv__
méthode. Ce n'est pas un opérateur en lui-même; le premier point est la partie de la valeur flottante, et la deuxième est l'opérateur de point pour accéder aux propriétés et méthodes des objets.Vous pouvez atteindre le même point en procédant comme suit.
Un autre exemple
Ici on ajoute 1,0 à 2,0, ce qui évidemment les rendements 3.0.
1.0+2
plus courte?1..toString()
1+2
et.1+.2
. Mon mauvais.La question est déjà suffisamment répondu (c'est à dire @Paul Rooneys réponse), mais il est également possible de vérifier l'exactitude de ces réponses.
Permettez-moi de récapituler les questions /réponses: Le
..
n'est pas un seul élément syntaxique!Vous pouvez vérifier le code source est "segmentées". Ces jetons représentent la façon dont le code est interprété:
La chaîne
1.
est interprétée comme un numéro, le deuxième.
est une OP (opérateur, dans ce cas, l'attribut" opérateur) et le__truediv__
est le nom de la méthode. Donc, c'est juste accès à la__truediv__
méthode du flotteur1.0
.Une autre façon de visualiser le bytecode généré est de
dis
assembler il. Cette montre, en réalité, les instructions qui sont exécutées lorsque le code est exécuté:Qui dit essentiellement la même. Il charge l'attribut
__truediv__
de la constante de1.0
.Concernant votre question
Même s'il est possible que vous ne devrait jamais écrire du code comme ça, tout simplement parce qu'il ne sait pas ce que fait le code. Donc merci de ne pas l'utiliser dans plus d'instructions complexes. J'irais même plus loin que vous ne devriez pas l'utiliser dans la "simple" états, au moins, vous devez utiliser des parenthèses pour séparer les instructions:
ce serait vraiment plus lisible - mais quelque chose le long des lignes de:
serait encore mieux!
L'approche à l'aide
partial
préserve également python du modèle de données (le1..__truediv__
approche ne fonctionne pas!) ce qui peut être démontrée par ce petit extrait:C'est parce que
1. /(1+2j)
n'est pas évalué parfloat.__truediv__
mais aveccomplex.__rtruediv__
-operator.truediv
fait en sorte que l'opération inverse est appelée lorsque le fonctionnement normal des retoursNotImplemented
mais vous n'avez pas ces réserves, quand vous travaillez sur__truediv__
directement. Cette perte de "comportement attendu" est la principale raison pour laquelle vous avez (normalement) ne doivent pas utiliser les méthodes magiques directement.Deux points ensemble peut être un peu déroutant au premier abord:
Mais c'est le même que l'écriture:
Parce que
float
littéraux peut être écrit sous trois formes:1.__truediv__
ne l'est pas?.
semble être analysée comme une partie du nombre, et puis le.
pour la méthode d'accesseur est manquant.f
est une limite de la méthode spéciale sur un flotteur avec une valeur de un. Plus précisément,en Python 3, invoque:
Preuve:
et:
Si nous n':
Nous conservons un nom lié à celui de la méthode liée
Si nous faisions cela parsemé de recherche dans une boucle serrée, cela pourrait sauver un peu de temps.
Analyse de l'Arbre de Syntaxe Abstraite (AST)
Nous pouvons voir que l'analyse de l'AST, l'expression nous dit que nous sommes le
__truediv__
attribut sur le nombre à virgule flottante,1.0
:Vous pourriez obtenir la même fonction à partir de:
Ou
Déduction
On peut aussi y aller par déduction.
Nous allons le construire.
1 par lui-même est un
int
:1 avec une période après c'est un float:
Le prochain point par lui-même serait une SyntaxError, mais il commence un pointillé de recherche sur l'instance du flotteur:
Personne n'a mentionné cette - C'est maintenant une "lié " méthode" sur le flotteur,
1.0
:Nous pourrions accomplir la même fonction beaucoup plus lisible:
Performance
La baisse de la
divide_one_by
fonction est qu'elle nécessite un autre Python cadre de la pile, le rendant légèrement plus lente que la méthode liée:Bien sûr, si vous pouvez simplement utiliser de la plaine des littéraux, c'est encore plus rapide: