>>> range(1,11)
дает вам
[1,2,3,4,5,6,7,8,9,10]
Почему не 1-11?
Они просто решили сделать это как это наугад или у него есть какое-то значение, которое я не вижу?
>>> range(1,11)
дает вам
[1,2,3,4,5,6,7,8,9,10]
Почему не 1-11?
Они просто решили сделать это как это наугад или у него есть какое-то значение, которое я не вижу?
Потому что чаще всего вызывается 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]
Эксклюзивные диапазоны имеют некоторые преимущества:
С одной стороны, каждый элемент в range(0,n)
является допустимым индексом для списков длины n
.
Кроме того, range(0,n)
имеет длину n
, а не n+1
, которая включает в себя всеохватывающий диапазон.
Он хорошо работает в сочетании с нулевым индексированием и 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()
.
Хотя здесь есть некоторые полезные алгоритмические объяснения, я думаю, что это может помочь добавить некоторые простые "реальные жизненные" рассуждения о том, почему он работает таким образом, который я нашел полезным при представлении предмета молодым новичкам:
С чем-то вроде "range (1,10)" путаница может возникнуть из-за того, что пара параметров представляет собой "начало и конец".
Это фактически начало и остановка.
Теперь, если это было значением "end", тогда да, вы можете ожидать, что число будет включено в качестве окончательной записи в последовательности. Но это не "конец".
Другие ошибочно называют этот параметр "count", потому что, если вы когда-либо используете "range (n)", то он, конечно же, повторяет "n" раз. Эта логика ломается при добавлении начального параметра.
Итак, ключевым моментом является запоминание его имени: " остановить". Это означает, что точка, по которой, когда она будет достигнута, итерация немедленно прекратится. Не после этой точки.
Итак, в то время как "start" действительно представляет первое значение, которое должно быть включено, при достижении значения "stop" оно "ломается", а не продолжает обрабатывать "тот же", прежде чем останавливаться.
Одна аналогия, которую я использовал в объяснении этого для детей, заключается в том, что, по иронии судьбы, лучше вести себя, чем детей! Он не останавливается после того, как он предположил - он немедленно останавливается, не заканчивая того, что он делает. (Они получают это;))
Другая аналогия - когда вы управляете автомобилем, вы не проходите знак остановки/выхода/ "уступить" и в конечном итоге сидите где-то рядом или сзади вашего автомобиля. Технически вы все еще не достигли этого, когда останавливаетесь. Он не включен в "вещи, которые вы прошли в своем путешествии".
Я надеюсь, что некоторые из них помогут объяснить Pythonitos/Pythonitas!
Он также полезен для диапазонов разделения; range(a,b)
можно разделить на range(a, x)
и range(x, b)
, тогда как с включенным диапазоном вы должны написать либо x-1
, либо x+1
. В то время как вам редко приходится разделять диапазоны, вы, как правило, часто разбиваете списки, что является одной из причин нарезки списка l[a:b]
включает в себя a-й элемент, но не b-й. Тогда range
, обладающее тем же свойством, делает его хорошо согласованным.
Длина диапазона - это верхнее значение минус нижнее значение.
Это очень похоже на что-то вроде:
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
Рассмотрим код
for i in range(10):
print "You'll see this 10 times", i
Идея состоит в том, что вы получаете список длины y-x
, который вы можете (как видите выше) перебирать.
Прочитайте документы python для диапазона - они рассматривают for-loop iteration основную usecase.