web-dev-qa-db-fra.com

Quelle est la raison d'avoir '//' en Python?

J'ai vu ceci dans le code de quelqu'un:

y = img_index // num_images

img_index est un index en cours d'exécution et num_images vaut 3.

Lorsque je plaisante avec // dans IPython, il semble agir comme un signe de division (c'est-à-dire une barre oblique). Je me demandais s'il y avait une raison pour avoir des doubles barres obliques?

366
Pete

Dans Python 3, ils ont obligé l'opérateur / à effectuer une division en virgule flottante et ont ajouté l'opérateur // à une division entière (c'est-à-dire un quotient sans reste); alors que dans Python 2, l'opérateur / était simplement une division entière, à moins que l'un des opérandes ne soit déjà un nombre à virgule flottante.

Dans Python 2.X:

>>> 10/3
3
>>> # to get a floating point number from integer division:
>>> 10.0/3
3.3333333333333335
>>> float(10)/3
3.3333333333333335

Dans Python 3:

>>> 10/3
3.3333333333333335
>>> 10//3
3

Pour plus de détails, voir PEP238 .

450
Mark Rushakoff

// est inconditionnellement une "division de revêtement de sol", par exemple:

>>> 4.0//1.5
2.0

Comme vous le voyez, même si les deux opérandes sont floats, // toujours les étages - vous savez donc toujours ce que ça va donner. faire.

Un seul / peut ou non dépendre de la version Python, des importations futures et même des drapeaux sur lesquels l'exécution de Python, par exemple ....:

$ python2.6 -Qold -c 'print 2/3'
0
$ python2.6 -Qnew -c 'print 2/3'
0.666666666667

Comme vous le voyez, un seul / peut prendre la parole, o il peut renvoyer un float, basé sur des problèmes complètement non locaux, jusqu'à la valeur de l'indicateur -Q incluse. .. ;-).

Donc, si et quand vous savez vous voulez un sol, utilisez toujours , utilisez //, qui le garantit. Si et quand vous vous connaissez ne pas voulez du revêtement de sol, glissez une float() autour d'un autre opérande et utilisez /. Toute autre combinaison, et vous êtes à la merci de la version, des importations et des drapeaux! -)

154
Alex Martelli

Pour compléter la réponse d'Alex, j'ajouterais que, à partir de Python 2.2.0a2, from __future__ import division est une alternative pratique à l'utilisation de beaucoup de float(…)/…. Toutes divisions exécutent float divisions, sauf celles avec //. Cela fonctionne avec toutes les versions à partir de 2.2.0a2.

21
Eric O Lebigot

Pour compléter ces autres réponses, l'opérateur // offre également des avantages de performance (3x) significatifs par rapport à /, en supposant que vous souhaitiez une division entière.

$ python -m timeit '20.5 // 2'
100000000 loops, best of 3: 0.0149 usec per loop
$ python -m timeit '20.5 / 2'
10000000 loops, best of 3: 0.0484 usec per loop
$ python -m timeit '20 / 2'
10000000 loops, best of 3: 0.043 usec per loop
$ python -m timeit '20 // 2'
100000000 loops, best of 3: 0.0144 usec per loop
16
user3733083

// peut être considéré comme un alias de math.floor () pour les divisions avec une valeur de retour de type float. Il fonctionne comme no-op pour les divisions avec une valeur de retour de type int.

import math
# let's examine `float` returns
# -------------------------------------
# divide
>>> 1.0 / 2
0.5
# divide and round down
>>> math.floor(1.0/2)
0.0
# divide and round down
>>> 1.0 // 2
0.0

# now let's examine `integer` returns
# -------------------------------------
>>> 1/2
0
>>> 1//2
0
8
un33k