>>> range(1,11)
дає тобі
[1,2,3,4,5,6,7,8,9,10]
Чому б не 1-11?
Вони просто вирішили зробити це так випадково або це має якесь значення, якого я не бачу?
range()
має сенс набагато частіше
>>> range(1,11)
дає тобі
[1,2,3,4,5,6,7,8,9,10]
Чому б не 1-11?
Вони просто вирішили зробити це так випадково або це має якесь значення, якого я не бачу?
range()
має сенс набагато частіше
Відповіді:
Тому що частіше називати той, 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, можливо, вам потрібно визначити власну функцію:
>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
range(start, count)
?
range(10)
еквівалентно range(0, 10)
.
range1
не будете працювати з діапазонами , які мають різний розмір кроку ніж 1
.
for i in range(len(li)):
є скоріше антипатерном. Слід використовувати enumerate
.
Хоча тут є кілька корисних алгоритмічних пояснень, я думаю, що це може допомогти додати кілька простих міркувань у реальному житті про те, чому це працює таким чином, що я вважаю корисним під час ознайомлення з темою для молодих новачків:
З чимось на зразок "діапазон (1,10)" плутанина може виникнути через думку, що пара параметрів являє собою "початок і кінець".
Це насправді початок і «зупинка».
Тепер, якби це було значення "кінець", так, так, ви можете очікувати, що це число буде включено як остаточний запис у послідовності. Але це не "кінець".
Інші помилково називають цей параметр "count", тому що якщо ви коли-небудь використовуватимете "range (n)", то він, звичайно, повторює "n" разів. Ця логіка руйнується, коли ви додаєте початковий параметр.
Тож ключовим моментом є запам’ятати його назву: « стоп ». Це означає, що це момент, коли досягнута, ітерація негайно припиниться. Не після цього моменту.
Отже, хоча "старт" справді являє собою перше значення, яке потрібно включити, після досягнення значення "стоп" воно "розбивається", а не продовжує обробляти "те", а також перед зупинкою.
Одна з аналогій, яку я використав, пояснюючи це дітям, - це те, що, за іронією долі, так краще вести себе, ніж діти! Вона не зупиняється після того, як вона повинна була - вона зупиняється негайно, не закінчуючи того, що робила. (Вони отримують це;))
Ще одна аналогія - коли ви керуєте автомобілем, ви не проходите знак зупинки / поступки / «поступайтеся дорогою» і в кінцевому підсумку сидите десь поруч або позаду свого автомобіля. Технічно ви досі не дійшли до цього, коли зупиняєтесь. Він не входить до «речей, які ти передав у дорогу».
Я сподіваюся, що щось із цього допоможе в поясненні Pythonitos / Pythonitas!
Він добре працює в поєднанні з нульовою індексацією та 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()
.
w = 'abc'; w[:] == w[0:len(w)]; w[:-1] == w[0:len(w)-1];
def full_range(start,stop): return range(start,stop+1) ## helper function
for index, item in enumerate(x)
щоб уникнути плутанини
Це також корисно для розділення діапазонів; 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
Однак Рубі визнає, що багато разів вам потрібно буде включити термінальне значення і пропонує альтернативний синтаксис:
1..10 #this is also a range from 1 to 10
1..10
проти 1...10
читання коду важко розрізнити!
В основному в пітоні range(n)
повторюється n
час, який має винятковий характер, тому він не дає останнього значення під час друку, ми можемо створити функцію, яка надає інклюзивне значення, це означає, що вона також буде друкувати останнє значення, згадане в діапазоні.
def main():
for i in inclusive_range(25):
print(i, sep=" ")
def inclusive_range(*args):
numargs = len(args)
if numargs == 0:
raise TypeError("you need to write at least a value")
elif numargs == 1:
stop = args[0]
start = 0
step = 1
elif numargs == 2:
(start, stop) = args
step = 1
elif numargs == 3:
(start, stop, step) = args
else:
raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
i = start
while i <= stop:
yield i
i += step
if __name__ == "__main__":
main()
Розглянемо код
for i in range(10):
print "You'll see this 10 times", i
Ідея полягає в тому, що ви отримуєте список довжини y-x
, який ви можете (як бачите вище) повторити.
Читайте на документах python для діапазону - вони вважають ітерацію для циклу основним шаблоном використання.
Просто зручніше міркувати в багатьох випадках.
В основному, ми могли б думати про діапазон як проміжок між start
і end
. Якщо start <= end
, довжина інтервалу між ними дорівнює end - start
. Якщо б len
насправді було визначено як довжину, ви мали б:
len(range(start, end)) == start - end
Однак ми підраховуємо цілі числа, включені в діапазон замість вимірювання довжини інтервалу. Щоб зберегти вищевказану властивість, ми повинні включити одну з кінцевих точок, а іншу виключити.
Додавання step
параметра - це як введення одиниці довжини. У такому випадку ви очікуєте
len(range(start, end, step)) == (start - end) / step
за довжиною. Щоб отримати підрахунок, ви просто використовуєте ціле ділення.