2010-12-21 2 views
175
>>> range(1,11) 

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

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

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

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

+18

'range (len (s))' –

+7

читать Dijkstra, ewd831 – SilentGhost

+3

В основном вы выбираете один набор ошибок один за другим для другого. Один набор, скорее всего, заставит ваши циклы заканчиваться раньше, а другой, скорее всего, вызовет исключение (или переполнение буфера на других языках). После того, как вы написали кучу кода, вы увидите, что выбор поведения 'range()' имеет смысл гораздо чаще –

ответ

150

Поскольку принято называть 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++).

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

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

Если бы это было рассуждение, параметры не были бы 'range (start, count)'? –

+0

ах, так что это действительно потому, что x может быть 0 – BigOmega

+2

@shogun. Начальное значение по умолчанию равно 0, т. Е. 'Range (10)' эквивалентно 'range (0, 10)'. – marcog

6

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

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

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

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

Кроме того, как диапазон Руби:

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

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

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

Gah! Я не использую Ruby, но могу себе представить, что '1..10' vs' 1 ... 10' трудно отличить при чтении кода! – marcog

+2

@marcog - когда вы знаете, что существуют две формы, ваши глаза настраиваются на разницу :) – Skilldrick

+8

Оператор диапазона Ruby прекрасно интуитивно понятен. Более длинная форма дает вам более короткую последовательность. * кашель * –

17

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

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

Также range(0,n) имеет длину n, а не n+1, которая будет включать в себя весь диапазон.

15

Он хорошо работает в сочетании с нулевым индексированием и 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().

+2

+1 для согласованности с нарезкой. –

+1

Соглашайтесь на нарезку. 'w = 'abc'; w [:] == w [0: len (w)]; w [: - 1] == w [0: len (w) -1]; ' – kevpie

+0

' def full_range (start, stop): диапазон возврата (запуск, останов + 1) ## вспомогательная функция – nobar

4

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

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

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

Читайте дальше the python docs для диапазона - они рассматривают for-loop итерацию первичной usecase.

8

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

9

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

Что-то вроде «диапазона (1,10)» может возникнуть из-за мышления о том, что пара параметров представляет «начало и конец».

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

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

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

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

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

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

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

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

Смежные вопросы