Beberapa pengukuran kinerja, menggunakan timeit
alih-alih mencoba melakukannya secara manual time
.
Pertama, Apple 2.7.2 64-bit:
In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop
Sekarang, python.org 3.3.0 64-bit:
In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop
In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop
In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.33 s per loop
Rupanya, 3.x range
benar-benar sedikit lebih lambat dari 2.x xrange
. Dan fungsi OP xrange
tidak ada hubungannya dengan itu. (Tidak mengherankan, karena panggilan satu kali ke __iter__
slot tidak akan terlihat di antara 10.000.000 panggilan untuk apa pun yang terjadi dalam loop, tetapi seseorang mengemukakannya sebagai suatu kemungkinan.)
Tapi ini hanya 30% lebih lambat. Bagaimana OP mendapat 2x lebih lambat? Nah, jika saya mengulangi tes yang sama dengan Python 32-bit, saya mendapatkan 1,58 vs 3,12. Jadi tebakan saya adalah bahwa ini adalah kasus lain di mana 3.x telah dioptimalkan untuk kinerja 64-bit dengan cara yang menyakitkan 32-bit.
Tetapi apakah itu benar-benar penting? Lihat ini, dengan 3.3.0 64-bit lagi:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop
Jadi, membangun list
membutuhkan lebih dari dua kali lebih lama dari seluruh iterasi.
Dan untuk "menghabiskan lebih banyak sumber daya daripada Python 2.6+", dari pengujian saya, sepertinya 3.x range
persis ukuran yang sama dengan 2.x xrange
—dan, bahkan jika itu 10x lebih besar, membangun daftar yang tidak perlu masih sekitar 10.000.000x lebih dari masalah daripada apa pun rentang iterasi mungkin bisa dilakukan.
Dan bagaimana dengan for
loop eksplisit, bukan loop C di dalam deque
?
In [87]: def consume(x):
....: for i in x:
....: pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop
Jadi, hampir sebanyak waktu yang terbuang dalam for
pernyataan seperti pada pekerjaan aktual iterasi range
.
Jika Anda khawatir tentang mengoptimalkan iterasi objek rentang, Anda mungkin mencari di tempat yang salah.
Sementara itu, Anda terus bertanya mengapa xrange
dihapus, tidak peduli berapa kali orang mengatakan hal yang sama kepada Anda, tetapi saya akan mengulanginya lagi: Tidak dihapus: diubah namanya menjadi range
, dan 2.x range
adalah yang dihapus.
Berikut beberapa bukti bahwa range
objek 3.3 adalah turunan langsung dari xrange
objek 2.x (dan bukan dari range
fungsi 2.x ): sumber ke 3.3range
dan 2.7xrange
. Anda bahkan dapat melihat riwayat perubahan (terkait dengan, saya percaya, perubahan yang menggantikan instance terakhir dari string "xrange" di mana saja dalam file).
Jadi, mengapa lebih lambat?
Pertama, mereka telah menambahkan banyak fitur baru. Untuk yang lain, mereka telah melakukan semua jenis perubahan di semua tempat (terutama di dalam iterasi) yang memiliki efek samping kecil. Dan ada banyak pekerjaan untuk secara dramatis mengoptimalkan berbagai kasus penting, bahkan jika kadang-kadang sedikit pesimis kasus yang kurang penting. Tambahkan semua ini, dan saya tidak terkejut bahwa iterasi range
secepat mungkin sekarang sedikit lebih lambat. Ini adalah salah satu dari kasus-kasus yang kurang penting yang tidak akan pernah dipedulikan oleh siapa pun. Tidak ada yang mungkin memiliki kasus penggunaan nyata di mana perbedaan kinerja ini adalah hotspot dalam kode mereka.
range
dalam Python 3.x berasalxrange
dari Python 2.x. Sebenarnya Python 2.xrange
yang dihapus.