>>> range(1,11)
Memberi anda
[1,2,3,4,5,6,7,8,9,10]
Kenapa tidak 1-11?
Apakah mereka hanya memutuskan untuk melakukannya secara acak atau memiliki nilai yang tidak saya lihat?
range()
masuk akal
>>> range(1,11)
Memberi anda
[1,2,3,4,5,6,7,8,9,10]
Kenapa tidak 1-11?
Apakah mereka hanya memutuskan untuk melakukannya secara acak atau memiliki nilai yang tidak saya lihat?
range()
masuk akal
Jawaban:
Karena itu lebih umum untuk memanggil range(0, 10)
yang mengembalikan [0,1,2,3,4,5,6,7,8,9]
yang berisi 10 elemen yang sama len(range(0, 10))
. Ingat bahwa programmer lebih suka pengindeksan berbasis 0.
Pertimbangkan juga cuplikan kode umum berikut:
for i in range(len(li)):
pass
Bisakah Anda melihat bahwa jika range()
naik tepat len(li)
bahwa ini akan bermasalah? Programmer akan perlu secara eksplisit mengurangi 1. ini juga mengikuti tren umum dari programmer lebih memilih for(int i = 0; i < 10; i++)
lebih for(int i = 0; i <= 9; i++)
.
Jika Anda sering memanggil rentang dengan permulaan 1, Anda mungkin ingin mendefinisikan fungsi Anda sendiri:
>>> 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)
setara dengan range(0, 10)
.
range1
tidak akan bekerja dengan rentang yang memiliki ukuran langkah berbeda dari 1
.
for i in range(len(li)):
lebih merupakan antipattern. Orang harus menggunakan enumerate
.
Meskipun ada beberapa penjelasan algoritmik yang berguna di sini, saya pikir mungkin membantu untuk menambahkan beberapa alasan 'kehidupan nyata' yang sederhana tentang mengapa ia bekerja dengan cara ini, yang menurut saya berguna ketika memperkenalkan subjek tersebut kepada pendatang baru:
Dengan sesuatu seperti 'rentang (1,10)' kebingungan dapat timbul dari pemikiran bahwa sepasang parameter mewakili "awal dan akhir".
Ini sebenarnya mulai dan "berhenti".
Sekarang, jika itu adalah nilai "akhir" maka, ya, Anda mungkin berharap nomor itu akan dimasukkan sebagai entri terakhir dalam urutan. Tapi itu bukan "akhir".
Yang lain secara keliru menyebut parameter itu "menghitung" karena jika Anda hanya menggunakan 'rentang (n)' maka itu tentu saja, ulangi 'n' kali. Logika ini rusak ketika Anda menambahkan parameter awal.
Jadi intinya adalah mengingat namanya: " stop ". Itu berarti itu adalah titik di mana, ketika tercapai, iterasi akan segera berhenti. Tidak setelah titik itu.
Jadi, sementara "mulai" memang mewakili nilai pertama yang akan dimasukkan, pada mencapai nilai "berhenti" itu 'rusak' daripada terus memproses 'yang juga' sebelum berhenti.
Satu analogi yang saya gunakan dalam menjelaskan ini kepada anak-anak adalah, ironisnya, itu lebih baik daripada anak-anak! Itu tidak berhenti setelah seharusnya - berhenti segera tanpa menyelesaikan apa yang dilakukannya. (Mereka mendapatkan ini;))
Analogi lain - ketika Anda mengendarai mobil Anda tidak melewati tanda berhenti / menyerah / 'memberi jalan' dan berakhir dengan itu duduk di suatu tempat di sebelah, atau di belakang, mobil Anda. Secara teknis Anda masih belum mencapainya ketika Anda berhenti. Itu tidak termasuk dalam 'hal-hal yang Anda lewati dalam perjalanan Anda'.
Saya harap beberapa dari itu membantu dalam menjelaskan kepada Pythonitos / Pythonitas!
Ini bekerja dengan baik dalam kombinasi dengan pengindeksan berbasis nol dan len()
. Misalnya, jika Anda memiliki 10 item dalam daftar x
, mereka diberi nomor 0-9. range(len(x))
memberi Anda 0-9.
Tentu saja, orang akan mengatakan kepada Anda bahwa itu lebih Pythonic untuk dilakukan for item in x
atau for index, item in enumerate(x)
bukan for i in range(len(x))
.
Mengiris juga berfungsi: foo[1:4]
adalah item 1-3 dari foo
(ingat bahwa item 1 sebenarnya item kedua karena pengindeksan berbasis nol). Untuk konsistensi, keduanya harus bekerja dengan cara yang sama.
Saya menganggapnya sebagai: "angka pertama yang Anda inginkan, diikuti oleh angka pertama yang tidak Anda inginkan." Jika Anda ingin 1-10, angka pertama yang tidak Anda inginkan adalah 11, jadi begitu range(1, 11)
.
Jika menjadi rumit dalam aplikasi tertentu, cukup mudah untuk menulis fungsi pembantu kecil yang menambahkan 1 ke indeks akhir dan panggilan 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)
untuk menghindari kebingungan
Ini juga berguna untuk rentang pemisahan; range(a,b)
dapat dibagi menjadi range(a, x)
dan range(x, b)
, sedangkan dengan rentang inklusif Anda akan menulis salah satu x-1
atau x+1
. Meskipun Anda jarang perlu membagi rentang, Anda cenderung untuk membagi daftar cukup sering, yang merupakan salah satu alasan mengiris daftar l[a:b]
termasuk elemen a tapi bukan b. Kemudian range
memiliki properti yang sama membuatnya konsisten.
Panjang rentang adalah nilai teratas dikurangi nilai bawah.
Ini sangat mirip dengan sesuatu seperti:
for (var i = 1; i < 11; i++) {
//i goes from 1 to 10 in here
}
dalam bahasa gaya-C.
Juga menyukai kisaran Ruby:
1...11 #this is a range from 1 to 10
Namun, Ruby mengakui bahwa berkali-kali Anda ingin memasukkan nilai terminal dan menawarkan sintaks alternatif:
1..10 #this is also a range from 1 to 10
1..10
vs 1...10
sulit dibedakan antara ketika membaca kode!
Pada dasarnya dalam python range(n)
iterates n
times, yang bersifat eksklusif itulah sebabnya ia tidak memberikan nilai terakhir ketika sedang dicetak, kita dapat membuat fungsi yang memberikan nilai inklusif artinya juga akan mencetak nilai terakhir yang disebutkan dalam range.
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()
Pertimbangkan kodenya
for i in range(10):
print "You'll see this 10 times", i
Idenya adalah bahwa Anda mendapatkan daftar panjang y-x
, yang Anda dapat (seperti yang Anda lihat di atas) beralih.
Baca pada python docs untuk rentang - mereka menganggap for-loop iteration sebagai usecase utama.
Dalam banyak kasus hanya lebih mudah untuk dipikirkan.
Pada dasarnya, kita bisa menganggap rentang sebagai interval antara start
dan end
. Jika start <= end
, panjang interval di antara mereka adalah end - start
. Jika len
sebenarnya didefinisikan sebagai panjang, Anda harus:
len(range(start, end)) == start - end
Namun, kami menghitung bilangan bulat yang termasuk dalam rentang alih-alih mengukur panjang interval. Agar properti di atas benar, kita harus memasukkan salah satu titik akhir dan mengecualikan yang lain.
Menambahkan step
parameter seperti memperkenalkan satuan panjang. Dalam hal ini, yang Anda harapkan
len(range(start, end, step)) == (start - end) / step
panjangnya. Untuk mendapatkan penghitungan, Anda hanya menggunakan divisi integer.