Почему диапазон (начало, конец) не включает конец?

>>> range(1,11)

дает вам

[1,2,3,4,5,6,7,8,9,10]

Почему не 1-11?

Они просто решили сделать это как это наугад или у него есть какое-то значение, которое я не вижу?

Ответ 1

Потому что чаще всего вызывается range(0, 10), который возвращает [0,1,2,3,4,5,6,7,8,9], который содержит 10 элементов, равных len(range(0, 10)). Помните, что программисты предпочитают индексирование на основе 0.

Также рассмотрим следующий общий фрагмент кода:

for i in range(len(li)):
  pass

Не могли бы вы увидеть, что если range() достиг точно ровно len(li), это было бы проблематично? Программисту нужно явно вычитать 1. Это также следует общей тенденции программистов, предпочитающих for(int i = 0; i < 10; i++) более for(int i = 0; i <= 9; i++).

Если вы часто вызываете диапазон с началом 1, вы можете определить свою собственную функцию:

>>> range1 = lambda start, end: range(start, end+1)
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Ответ 2

Эксклюзивные диапазоны имеют некоторые преимущества:

С одной стороны, каждый элемент в range(0,n) является допустимым индексом для списков длины n.

Кроме того, range(0,n) имеет длину n, а не n+1, которая включает в себя всеохватывающий диапазон.

Ответ 3

Он хорошо работает в сочетании с нулевым индексированием и len(). Например, если у вас есть 10 элементов в списке x, они пронумерованы 0-9. range(len(x)) дает вам 0-9.

Конечно, люди скажут вам, что более Pythonic делает for item in x или for index, item in enumerate(x), а не for i in range(len(x)).

Нарезка тоже работает: foo[1:4] - это пункты 1-3 из foo (имея в виду, что элемент 1 на самом деле является вторым элементом из-за индексации на основе нуля). Для согласованности они должны работать одинаково.

Я думаю об этом как: "первый номер, который вы хотите, за которым следует первый номер, который вам не нужен". Если вы хотите 1-10, первое число, которое вам не нужно, равно 11, поэтому оно range(1, 11).

Если он становится громоздким в конкретном приложении, достаточно легко написать небольшую вспомогательную функцию, которая добавляет 1 к концу индекса и вызывает range().

Ответ 4

Хотя здесь есть некоторые полезные алгоритмические объяснения, я думаю, что это может помочь добавить некоторые простые "реальные жизненные" рассуждения о том, почему он работает таким образом, который я нашел полезным при представлении предмета молодым новичкам:

С чем-то вроде "range (1,10)" путаница может возникнуть из-за того, что пара параметров представляет собой "начало и конец".

Это фактически начало и остановка.

Теперь, если это было значением "end", тогда да, вы можете ожидать, что число будет включено в качестве окончательной записи в последовательности. Но это не "конец".

Другие ошибочно называют этот параметр "count", потому что, если вы когда-либо используете "range (n)", то он, конечно же, повторяет "n" раз. Эта логика ломается при добавлении начального параметра.

Итак, ключевым моментом является запоминание его имени: " остановить". Это означает, что точка, по которой, когда она будет достигнута, итерация немедленно прекратится. Не после этой точки.

Итак, в то время как "start" действительно представляет первое значение, которое должно быть включено, при достижении значения "stop" оно "ломается", а не продолжает обрабатывать "тот же", прежде чем останавливаться.

Одна аналогия, которую я использовал в объяснении этого для детей, заключается в том, что, по иронии судьбы, лучше вести себя, чем детей! Он не останавливается после того, как он предположил - он немедленно останавливается, не заканчивая того, что он делает. (Они получают это;))

Другая аналогия - когда вы управляете автомобилем, вы не проходите знак остановки/выхода/ "уступить" и в конечном итоге сидите где-то рядом или сзади вашего автомобиля. Технически вы все еще не достигли этого, когда останавливаетесь. Он не включен в "вещи, которые вы прошли в своем путешествии".

Я надеюсь, что некоторые из них помогут объяснить Pythonitos/Pythonitas!

Ответ 5

Он также полезен для диапазонов разделения; range(a,b) можно разделить на range(a, x) и range(x, b), тогда как с включенным диапазоном вы должны написать либо x-1, либо x+1. В то время как вам редко приходится разделять диапазоны, вы, как правило, часто разбиваете списки, что является одной из причин нарезки списка l[a:b] включает в себя a-й элемент, но не b-й. Тогда range, обладающее тем же свойством, делает его хорошо согласованным.

Ответ 6

Длина диапазона - это верхнее значение минус нижнее значение.

Это очень похоже на что-то вроде:

for (var i = 1; i < 11; i++) {
    //i goes from 1 to 10 in here
}

на языке C-стиля.

Также как диапазон Ruby:

1...11 #this is a range from 1 to 10

Однако Ruby признает, что много раз вы хотите включить значение терминала и предлагает альтернативный синтаксис:

1..10 #this is also a range from 1 to 10

Ответ 7

Рассмотрим код

for i in range(10):
    print "You'll see this 10 times", i

Идея состоит в том, что вы получаете список длины y-x, который вы можете (как видите выше) перебирать.

Прочитайте документы python для диапазона - они рассматривают for-loop iteration основную usecase.