Kapan Anda harus menggunakan ekspresi generator dan kapan Anda harus menggunakan daftar pemahaman dalam Python?
# Generator expression
(x*2 for x in range(256))
# List comprehension
[x*2 for x in range(256)]
python
list-comprehension
generator
Hanya baca
sumber
sumber
[exp for x in iter]
hanya bisa menjadi gula untuklist((exp for x in iter))
? atau apakah ada perbedaan eksekusi?X = [x**2 for x in range(5)]; print x
denganY = list(y**2 for y in range(5)); print y
, yang kedua akan memberikan kesalahan. Dalam Python3, pemahaman daftar memang gula sintaksis untuk ekspresi generator diumpankanlist()
seperti yang Anda harapkan, sehingga variabel loop tidak akan lagi bocor .Jawaban:
Jawaban John adalah baik (daftar itu lebih baik bila Anda ingin mengulangi sesuatu berulang kali). Namun, perlu dicatat bahwa Anda harus menggunakan daftar jika Anda ingin menggunakan salah satu metode daftar. Misalnya, kode berikut tidak akan berfungsi:
Pada dasarnya, gunakan ekspresi generator jika semua yang Anda lakukan adalah iterasi satu kali. Jika Anda ingin menyimpan dan menggunakan hasil yang dihasilkan, maka Anda mungkin lebih baik dengan pemahaman daftar.
Karena kinerja adalah alasan paling umum untuk memilih satu di atas yang lain, saran saya adalah jangan khawatir tentang itu dan hanya memilih satu; jika Anda menemukan bahwa program Anda berjalan terlalu lambat, maka dan hanya kemudian Anda harus kembali dan khawatir tentang penyetelan kode Anda.
sumber
a = [1, 2, 3] b = [4, 5, 6] a.extend(b)
- a sekarang akan [1, 2, 3, 4, 5, 6]. (Bisakah Anda menambahkan baris baru dalam komentar ??)a = (x for x in range(0,10)), b = [1,2,3]
contohnya.a.extend(b)
melempar pengecualian.b.extend(a)
akan mengevaluasi semua dari, dalam hal ini tidak ada gunanya menjadikannya generator di tempat pertama.Iterasi atas ekspresi generator atau pemahaman daftar akan melakukan hal yang sama. Namun, pemahaman daftar akan membuat seluruh daftar di memori terlebih dahulu sementara ekspresi generator akan membuat item dengan cepat, sehingga Anda dapat menggunakannya untuk urutan yang sangat besar (dan juga tak terbatas!).
sumber
itertools.count(n)
adalah urutan bilangan bulat tak terbatas, mulai dari n, sehingga(2 ** item for item in itertools.count(n))
akan menjadi urutan tak terbatas dari kekuatan2
mulai dari2 ** n
.Gunakan pemahaman daftar ketika hasilnya perlu diulang beberapa kali, atau di mana kecepatan sangat penting. Gunakan ekspresi generator di mana kisarannya besar atau tidak terbatas.
Lihat Ekspresi generator dan daftar pemahaman untuk info lebih lanjut.
sumber
lists
apakah lebih cepat darigenerator
ekspresi? Dari membaca jawaban dF, terlihat bahwa itu adalah sebaliknya.Poin penting adalah bahwa pemahaman daftar membuat daftar baru. Generator menciptakan objek yang dapat diubah yang akan "memfilter" bahan sumber saat Anda mengkonsumsi bit.
Bayangkan Anda memiliki file log 2TB yang disebut "hugefile.txt", dan Anda menginginkan konten dan panjang untuk semua baris yang dimulai dengan kata "ENTRY".
Jadi Anda mencoba memulai dengan menulis daftar pemahaman:
Ini menyeruput seluruh file, memproses setiap baris, dan menyimpan baris yang cocok dalam array Anda. Oleh karena itu array ini dapat memuat konten hingga 2TB. Itu banyak RAM, dan mungkin tidak praktis untuk keperluan Anda.
Jadi alih-alih, kita dapat menggunakan generator untuk menerapkan "filter" ke konten kita. Tidak ada data yang benar-benar dibaca sampai kita mulai mengulangi hasilnya.
Bahkan satu baris pun belum dibaca dari file kami. Bahkan, katakanlah kami ingin memfilter hasil kami lebih jauh:
Masih belum ada yang dibaca, tetapi kami telah menentukan sekarang dua generator yang akan bertindak berdasarkan data kami seperti yang kami inginkan.
Mari kita menulis baris yang difilter ke file lain:
Sekarang kita membaca file input. Ketika
for
loop kami terus meminta jalur tambahan,long_entries
generator meminta jalur darientry_lines
generator, hanya mengembalikan yang panjangnya lebih dari 80 karakter. Dan pada gilirannya,entry_lines
generator meminta baris (difilter seperti yang ditunjukkan) darilogfile
iterator, yang pada gilirannya membaca file.Jadi, alih-alih "mendorong" data ke fungsi output Anda dalam bentuk daftar yang terisi penuh, Anda memberikan fungsi output cara untuk "menarik" data hanya saat dibutuhkan. Ini dalam kasus kami jauh lebih efisien, tetapi tidak cukup fleksibel. Generator adalah satu arah, satu lintasan; data dari file log yang telah kita baca segera dibuang, jadi kita tidak bisa kembali ke baris sebelumnya. Di sisi lain, kita tidak perlu khawatir tentang menyimpan data setelah kita selesai dengan itu.
sumber
Manfaat dari ekspresi generator adalah ia menggunakan lebih sedikit memori karena tidak membangun seluruh daftar sekaligus. Ekspresi generator paling baik digunakan ketika daftar adalah perantara, seperti menjumlahkan hasil, atau membuat dict dari hasil.
Sebagai contoh:
Keuntungannya adalah bahwa daftar tersebut tidak sepenuhnya dihasilkan, dan dengan demikian sedikit memori yang digunakan (dan juga harus lebih cepat)
Namun, Anda harus menggunakan pemahaman daftar ketika produk akhir yang diinginkan adalah daftar. Anda tidak akan menyimpan memeory menggunakan ekspresi generator, karena Anda ingin daftar yang dihasilkan. Anda juga mendapatkan manfaat dari dapat menggunakan salah satu fungsi daftar seperti diurutkan atau dibalik.
Sebagai contoh:
sumber
sum(x*2 for x in xrange(256))
sorted
danreversed
bekerja dengan baik pada setiap iterable, termasuk ekspresi generator.Saat membuat generator dari objek yang bisa berubah-ubah (seperti daftar), ketahuilah bahwa generator akan dievaluasi pada keadaan daftar saat menggunakan generator, bukan pada saat pembuatan generator:
Jika ada kemungkinan daftar Anda diubah (atau objek yang bisa berubah di dalam daftar itu) tetapi Anda memerlukan status saat membuat generator, Anda harus menggunakan pemahaman daftar.
sumber
Kadang-kadang Anda dapat pergi dengan fungsi tee dari itertools , ia mengembalikan beberapa iterator untuk generator yang sama yang dapat digunakan secara mandiri.
sumber
Saya menggunakan modul Hadoop Mincemeat . Saya pikir ini adalah contoh yang bagus untuk mencatat:
Di sini generator mengeluarkan angka dari file teks (sebesar 15GB) dan menerapkan matematika sederhana pada angka-angka tersebut menggunakan pengurangan peta Hadoop. Jika saya tidak menggunakan fungsi hasil, tetapi sebagai daftar pemahaman, itu akan memakan waktu lebih lama menghitung jumlah dan rata-rata (belum lagi kompleksitas ruang).
Hadoop adalah contoh yang bagus untuk menggunakan semua keunggulan Generator.
sumber