Apa perbedaan antara iterator dan generator? Beberapa contoh kapan Anda akan menggunakan setiap kasing akan sangat membantu.
iterator
adalah konsep yang lebih umum: objek apa pun yang kelasnya memiliki next
metode ( __next__
dengan Python 3) dan __iter__
metode yang melakukannya return self
.
Setiap generator adalah iterator, tetapi tidak sebaliknya. Generator dibangun dengan memanggil fungsi yang memiliki satu atau lebih yield
ekspresi ( yield
pernyataan, dalam Python 2.5 dan sebelumnya), dan merupakan objek yang memenuhi definisi paragraf sebelumnya tentang suatu iterator
.
Anda mungkin ingin menggunakan iterator khusus, bukan generator, ketika Anda membutuhkan kelas dengan perilaku pemeliharaan keadaan yang agak rumit, atau ingin mengekspos metode lain selain next
(dan __iter__
dan __init__
). Paling sering, generator (kadang-kadang, untuk kebutuhan yang cukup sederhana, ekspresi generator ) cukup, dan lebih mudah untuk dikodekan karena pemeliharaan negara (dalam batas yang wajar) pada dasarnya "dilakukan untuk Anda" oleh frame yang ditangguhkan dan dilanjutkan.
Misalnya, generator seperti:
def squares(start, stop):
for i in range(start, stop):
yield i * i
generator = squares(a, b)
atau ekspresi generator yang setara (genexp)
generator = (i*i for i in range(a, b))
akan membutuhkan lebih banyak kode untuk dibuat sebagai iterator khusus:
class Squares(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop
def __iter__(self): return self
def next(self): # __next__ in Python 3
if self.start >= self.stop:
raise StopIteration
current = self.start * self.start
self.start += 1
return current
iterator = Squares(a, b)
Tetapi, tentu saja, dengan kelas Squares
Anda dapat dengan mudah menawarkan metode tambahan, yaitu
def current(self):
return self.start
jika Anda benar-benar membutuhkan fungsionalitas ekstra dalam aplikasi Anda.
for ... in ...:
, diteruskan ke fungsi, atau Anda akan meneleponiter.next()
for..in
sintaks. Mungkin saya kehilangan sesuatu, tetapi beberapa waktu yang lalu, saya tidak ingat jika saya menyelesaikannya. Terima kasih!Singkatnya: Iterator adalah objek yang memiliki metode
__iter__
and__next__
(next
in Python 2). Generator menyediakan cara bawaan yang mudah untuk membuat instance dari Iterators.Fungsi dengan hasil di dalamnya masih merupakan fungsi, yang, ketika dipanggil, mengembalikan turunan objek generator:
Ekspresi generator juga mengembalikan generator:
Untuk eksposisi dan contoh yang lebih mendalam, teruslah membaca.
Generator adalah Iterator
Secara khusus, generator adalah subtipe dari iterator.
Kita dapat membuat generator dengan beberapa cara. Cara yang sangat umum dan sederhana untuk melakukannya adalah dengan suatu fungsi.
Secara khusus, fungsi dengan hasil di dalamnya adalah fungsi, yang ketika dipanggil, mengembalikan generator:
Dan generator, sekali lagi, adalah Iterator:
Iterator adalah Iterable
Iterator adalah Iterable,
yang membutuhkan
__iter__
metode yang mengembalikan Iterator:Beberapa contoh iterables adalah built-in tuple, daftar, kamus, set, set beku, string, byte string, byte array, range dan memoryviews:
Iterator membutuhkan metode
next
atau a__next__
Dengan Python 2:
Dan dengan Python 3:
Kita bisa mendapatkan iterator dari objek bawaan (atau objek khusus) dengan
iter
fungsi:The
__iter__
metode ini disebut ketika Anda mencoba untuk menggunakan objek dengan untuk loop. Kemudian__next__
metode ini dipanggil pada objek iterator untuk mendapatkan setiap item untuk loop. Iterator munculStopIteration
ketika Anda telah kehabisan, dan itu tidak dapat digunakan kembali pada saat itu.Dari dokumentasi
Dari bagian Generator Type dari bagian Tipe Iterator dari dokumentasi Built-in Type :
(Penekanan ditambahkan.)
Jadi dari sini kita belajar bahwa Generator adalah jenis Iterator (nyaman).
Contoh Objek Iterator
Anda dapat membuat objek yang mengimplementasikan protokol Iterator dengan membuat atau memperluas objek Anda sendiri.
Tetapi lebih mudah menggunakan Generator untuk melakukan ini:
Atau mungkin lebih sederhana, Ekspresi Generator (bekerja serupa dengan daftar pemahaman):
Semua itu dapat digunakan dengan cara yang sama:
Kesimpulan
Anda dapat menggunakan protokol Iterator secara langsung ketika Anda perlu memperluas objek Python sebagai objek yang dapat diulangi.
Namun, dalam sebagian besar kasus, Anda paling cocok digunakan
yield
untuk mendefinisikan fungsi yang mengembalikan Generator Iterator atau mempertimbangkan Ekspresi Generator.Akhirnya, perhatikan bahwa generator menyediakan fungsionalitas lebih sebagai coroutine. Saya menjelaskan Generator, bersama dengan
yield
pernyataan, secara mendalam pada jawaban saya untuk "Apa kata kunci" hasil "lakukan?".sumber
Iterator:
Iterator adalah objek yang menggunakan
next()
metode untuk mendapatkan nilai urutan berikutnya.Generator:
Generator adalah fungsi yang menghasilkan atau menghasilkan urutan nilai menggunakan
yield
metode.Setiap
next()
panggilan metode pada objek generator (untuk contoh:f
seperti dalam contoh di bawah ini) dikembalikan oleh fungsi generator (misalnya:foo()
fungsi dalam contoh di bawah), menghasilkan nilai berikutnya secara berurutan.Ketika fungsi generator dipanggil, ia mengembalikan objek generator bahkan tanpa memulai eksekusi fungsi. Ketika
next()
metode dipanggil untuk pertama kalinya, fungsi mulai mengeksekusi sampai mencapai pernyataan hasil yang mengembalikan nilai yang dihasilkan. Hasil melacak yaitu mengingat eksekusi terakhir. Dannext()
panggilan kedua berlanjut dari nilai sebelumnya.Contoh berikut menunjukkan interaksi antara hasil dan panggilan ke metode selanjutnya pada objek generator.
sumber
Menambahkan jawaban karena tidak ada jawaban yang ada yang secara khusus mengatasi kebingungan dalam literatur resmi.
Fungsi generator adalah fungsi biasa yang didefinisikan menggunakan
yield
alih-alihreturn
. Ketika dipanggil, fungsi generator mengembalikan objek generator , yang merupakan sejenis iterator - ia memilikinext()
metode. Saat Anda meneleponnext()
, nilai selanjutnya yang dihasilkan oleh fungsi generator dikembalikan.Baik fungsi atau objek dapat disebut "generator" tergantung pada dokumen sumber Python yang Anda baca. Daftar istilah Python mengatakan fungsi generator, sedangkan wiki Python menyiratkan objek generator. The Python tutorial sangat berhasil menyiratkan baik penggunaan di ruang tiga kalimat:
Dua kalimat pertama mengidentifikasi generator dengan fungsi generator, sedangkan kalimat ketiga mengidentifikasi mereka dengan objek generator.
Terlepas dari semua kebingungan ini, orang dapat mencari referensi bahasa Python untuk kata yang jelas dan terakhir:
Jadi, dalam penggunaan formal dan tepat, "generator" tidak memenuhi syarat berarti objek generator, bukan fungsi generator.
Referensi di atas adalah untuk Python 2 tetapi referensi bahasa Python 3 mengatakan hal yang sama. Namun, daftar istilah Python 3 menyatakan itu
sumber
Semua orang memiliki jawaban yang sangat bagus dan jelas dengan contoh-contoh dan saya sangat menghargainya. Saya hanya ingin memberikan jawaban singkat untuk orang-orang yang secara konsep masih belum jelas:
Jika Anda membuat iterator Anda sendiri, ini sedikit terlibat - Anda harus membuat kelas dan setidaknya mengimplementasikan iter dan metode selanjutnya. Tetapi bagaimana jika Anda tidak ingin melalui kerumitan ini dan ingin cepat membuat iterator. Untungnya, Python menyediakan cara pintas untuk mendefinisikan iterator. Yang perlu Anda lakukan adalah mendefinisikan fungsi dengan setidaknya 1 panggilan untuk menghasilkan dan sekarang ketika Anda memanggil fungsi itu akan mengembalikan " sesuatu " yang akan bertindak seperti iterator (Anda dapat memanggil metode selanjutnya dan menggunakannya dalam for loop). Sesuatu ini memiliki nama dalam Python yang disebut Generator
Harapan itu sedikit memperjelas.
sumber
Jawaban sebelumnya melewatkan penambahan ini: generator memiliki
close
metode, sedangkan iterator tipikal tidak. Theclose
Metode pemicu sebuahStopIteration
pengecualian dalam generator, yang mungkin terjebak dalamfinally
klausul dalam iterator itu, untuk mendapatkan kesempatan untuk menjalankan beberapa bersih-bersih. Abstraksi ini membuatnya paling bisa digunakan dalam iterator besar daripada sederhana. Orang dapat menutup generator seperti orang dapat menutup file, tanpa harus repot dengan apa yang ada di bawahnya.Yang mengatakan, jawaban pribadi saya untuk pertanyaan pertama adalah: iteratable hanya memiliki
__iter__
metode, iterators khas hanya memiliki__next__
metode, generator memiliki kedua__iter__
dan satu__next__
dan tambahanclose
.Untuk pertanyaan kedua, jawaban pribadi saya adalah: di antarmuka publik, saya cenderung lebih menyukai generator, karena lebih tangguh:
close
metode yang komposisinya lebih besaryield from
. Secara lokal, saya dapat menggunakan iterator, tetapi hanya jika itu adalah struktur datar dan sederhana (iterator tidak mudah dikomposisi) dan jika ada alasan untuk percaya urutannya agak pendek terutama jika dapat dihentikan sebelum mencapai akhir. Saya cenderung memandang iterator sebagai primitif tingkat rendah, kecuali sebagai literal.Untuk masalah aliran kontrol, generator adalah konsep yang sama pentingnya dengan janji: keduanya abstrak dan dapat disusun.
sumber
__iter__
metode, bagaimana bisa iterator__next__
hanya memiliki ? Jika mereka seharusnya iterables, saya harapkan mereka__iter__
juga harus begitu.__iter__
on iterables untuk mengembalikan iterator, yang hanya membutuhkannext
metode (__next__
dalam Python3). Tolong jangan bingung standar (untuk mengetik bebek) dengan implementasinya (bagaimana juru bahasa Python tertentu menerapkannya). Ini agak seperti kebingungan antara fungsi generator (definisi) dan objek generator (implementasi). ;)Sebuah fungsi Generator adalah seperti fungsi biasa dengan Python tapi mengandung satu atau lebih
yield
pernyataan. Fungsi generator adalah alat yang hebat untuk membuat objek Iterator semudah mungkin. The Iterator objek returend oleh function generator juga disebut objek Generator atau Generator .Dalam contoh ini saya telah membuat fungsi Generator yang mengembalikan objek Generator
<generator object fib at 0x01342480>
. Sama seperti iterator lainnya, objek Generator dapat digunakan dalam satufor
lingkaran atau dengan fungsinext()
bawaan yang mengembalikan nilai berikutnya dari generator.Jadi fungsi generator adalah cara termudah untuk membuat objek Iterator.
Setiap objek generator adalah iterator tetapi tidak sebaliknya. Objek iterator kustom dapat dibuat jika kelasnya mengimplementasikan
__iter__
dan__next__
metode (juga disebut protokol iterator).Namun, jauh lebih mudah untuk menggunakan fungsi generator untuk membuat iterator karena mereka menyederhanakan pembuatannya, tetapi Iterator khusus memberi Anda lebih banyak kebebasan dan Anda juga dapat menerapkan metode lain sesuai dengan kebutuhan Anda seperti yang ditunjukkan pada contoh di bawah ini.
sumber
Contoh dari Ned Batchelder sangat direkomendasikan untuk iterator dan generator
Sebuah metode tanpa generator yang melakukan sesuatu ke angka genap
sementara dengan menggunakan generator
return
pernyataanMemanggil
evens
metode (generator) seperti biasaIterator
dan bookmark ini tidak ada hubungannya kecuali bergerak
next
Untuk menggunakan Generator ... kita membutuhkan suatu fungsi
Untuk menggunakan Iterator ... kita perlu
next
daniter
Seperti yang dikatakan:
Manfaat Seluruh Iterator:
sumber
Anda dapat membandingkan kedua pendekatan untuk data yang sama:
Selain itu, jika Anda memeriksa jejak memori, generator mengambil lebih sedikit memori karena tidak perlu menyimpan semua nilai dalam memori secara bersamaan.
sumber
Saya menulis khusus untuk pemula Python dengan cara yang sangat sederhana, meskipun jauh di lubuk hati Python melakukan banyak hal.
Mari kita mulai dengan yang paling mendasar:
Pertimbangkan daftar,
Mari kita menulis fungsi yang setara:
o / p dari
print(l): [1,2,3]
& o / p dariprint(f()) : [1,2,3]
Mari kita buat daftar l iterable: Dalam daftar python selalu iterable yang berarti Anda dapat menerapkan iterator kapan pun Anda inginkan.
Mari kita terapkan iterator pada daftar:
Mari kita membuat fungsi yang dapat diubah, yaitu menulis fungsi generator yang setara. Dengan python segera setelah Anda memasukkan kata kunci
yield
; itu menjadi fungsi generator dan iterator akan diterapkan secara implisit.Catatan: Setiap generator selalu iterable dengan iterator implisit diterapkan dan di sini iterator implisit adalah yang terpenting Jadi fungsi generator adalah:
Jadi jika Anda telah mengamati, segera setelah Anda membuat generator fungsi fa, itu sudah iter (f)
Sekarang,
Ini agaknya Anda casting int ke int (x) yang sudah int dan itu akan tetap int (x).
Misalnya o / p dari:
adalah
Jangan pernah lupa ini adalah Python dan bukan C atau C ++
Maka kesimpulan dari penjelasan di atas adalah:
sumber