В чем причина наличия символа // в Python?

Я видел это в чьем-то коде:

y = img_index // num_images

где img_index - текущий индекс, а num_images - 3.

Когда я возился с // в IPython, кажется, что он действует как знак деления (т. Е. Один косая черта). Мне просто интересно, есть ли причина для двойных косых черт?


person Pete    schedule 08.10.2009    source источник


Ответы (5)


В Python 3 они заставили оператор / выполнять деление с плавающей запятой и добавили оператор // для целочисленного деления (т.е. частное без остатка); тогда как в Python 2 оператор / был просто целочисленным делением, если только один из операндов уже не был числом с плавающей запятой.

В 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

В Python 3:

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

Для получения дополнительной информации см. PEP238.

person Mark Rushakoff    schedule 08.10.2009
comment
На самом деле мне больше нравится этот стиль ... Я могу вспомнить, по крайней мере, на одном языке, который я использовал (VB?), Дифференцирующий фактор был / против \ ... но я никогда не мог вспомнить, какой из них был! - person Matthew Scharley; 08.10.2009
comment
PEP также учитывает тот факт, что обратная косая черта зарезервирована для escape-символов или escape-символов новой строки, так что этот вид немедленно исключил \ как оператор. - person Mark Rushakoff; 08.10.2009
comment
Спасибо, я был занят Python 3+ в течение некоторого времени, и я никогда не знал этого, я всегда делал int(n/i). Отличная информация здесь! - person Hidde; 20.08.2012
comment
Подход Python 2 к / на самом деле неплох. В SQL нам тоже приходится иметь дело с этим. Обычно можно увидеть (0,0 + переменная1) / переменная2 или 1,0 * переменная1 / переменная2 - person Chris; 28.10.2015

// - безусловно, разделение полов, например:

>>> 4.0//1.5
2.0

Как видите, даже несмотря на то, что оба операнда floats, // все еще этажи - так что вы всегда надежно знаете, что он собирается делать.

Одиночный / может или не может быть перекрытым, в зависимости от выпуска Python, будущего импорта и даже флагов, на которых запускается Python, например:

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

Как видите, single / может возвращать значение с плавающей запятой, или оно может возвращать значение с плавающей запятой, исходя из совершенно нелокальных проблем, вплоть до значения флага -Q ... ;-).

Итак, если и когда вы знаете, что хотите пол, всегда используйте //, который гарантирует это. Если и когда вы знаете, что не хотите пол, поставьте float() вокруг другого операнда и используйте /. Любая другая комбинация, и вы зависите от версии, импорта и флагов! -)

person Alex Martelli    schedule 08.10.2009
comment
Интересно, что // усечение по-прежнему возвращает число с плавающей запятой. - person Lucretiel; 18.09.2013
comment
Оператор // выполняет деление по полу, а не усекающее / усеченное деление. - person Peter John Acklam; 31.03.2015
comment
Это более прямой ответ, основанный на природе вопроса, imho. Ответ с более высокими оценками полезен, но он дает кристально ясную картину, почему в Python2 вы бы предпочли один другому. - person Peter M. Elias; 14.01.2016
comment
@PeterJohnAcklam, это правда, но странно, что // возвращает число с плавающей запятой, когда для многих людей деление по полу и целочисленное деление тесно связаны. Какой самый питонический способ получить целое число от деления этажа? int (a // b)? - person Shuklaswag; 20.12.2017
comment
@Lucretiel, может быть, это изменилось в более поздних версиях Python? type(2//3) в Python 3.8.6 возвращает мне <class 'int'>. - person Mark Ransom; 18.06.2021

В дополнение к этим другим ответам оператор // также предлагает значительные (3x) преимущества в производительности по сравнению с /, если предполагается, что вам нужно целочисленное деление.

$ python -m timeit '20.5 // 2'
100,000,000 loops, best of 3: 14.9 nsec per loop

$ python -m timeit '20.5 / 2'
 10,000,000 loops, best of 3: 48.4 nsec per loop

$ python -m timeit '20 / 2'
 10,000,000 loops, best of 3: 43.0 nsec per loop

$ python -m timeit '20 // 2'
100,000,000 loops, best of 3: 14.4 nsec per loop
person user3733083    schedule 20.02.2015
comment
Я пробовал это с Python 3 (Python 3.8.5), и все четыре работали на < b> одинаковая скорость. Пример выполнения: 9,24 нс, 9,40, 9,22 и 9,34 нс на цикл. (ЦП: AMD FX-4300 3,8 ГГц (четыре ядра) . Материнская плата: Gigabyte Technology GA-970A-DS3P. Операционная система: Linux (Ubuntu MATE 20.04 (Focal Fossa) с корицей).) - person Peter Mortensen; 01.12.2020
comment
Таким образом, оспаривается трехкратное увеличение производительности оператора //. - person Peter Mortensen; 01.12.2020
comment
Все еще верно для Python 2, который все еще широко используется по сей день. - person MacK; 28.01.2021

Чтобы дополнить ответ Алекса, я бы добавил что, начиная с Python 2.2.0a2, from __future__ import division является удобной альтернативой использованию большого количества float(…)/…. Все деления выполняют деления float, кроме тех, у которых есть //. Это работает со всеми версиями, начиная с 2.2.0a2.

person Eric O Lebigot    schedule 08.10.2009

// можно рассматривать как псевдоним math.floor () для подразделений с возвращаемым значением типа float. Он работает как no-op для подразделений с возвращаемым значением типа 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
person un33k    schedule 22.09.2014