penjana

1. Kenapa kita perlukan generator

Melalui pembelajaran di atas, kita boleh tahu formula penjanaan senarai, dan kita boleh terus buat senarai. Walau bagaimanapun, disebabkan kekangan ingatan, kapasiti senarai pasti terhad. Selain itu, mencipta senarai yang mengandungi 10 juta elemen bukan sahaja mengambil banyak ruang storan, tetapi jika kita hanya perlu mengakses beberapa elemen pertama, ruang yang diduduki oleh kebanyakan elemen berikutnya adalah sia-sia.

Jadi, jika elemen senarai boleh dikira mengikut algoritma tertentu, bolehkah kita terus mengira elemen seterusnya semasa gelung? Ini menjimatkan banyak ruang dengan tidak perlu membuat senarai lengkap. Dalam Python, mekanisme gelung dan pengiraan pada masa yang sama dipanggil penjana: penjana.

Dalam Python, fungsi yang menggunakan hasil dipanggil penjana.

Berbeza dengan fungsi biasa, penjana adalah fungsi yang mengembalikan iterator dan hanya boleh digunakan untuk operasi lelaran Lebih mudah untuk memahami bahawa penjana adalah lelaran.

Dalam proses memanggil penjana untuk dijalankan, setiap kali ia menemui hasil, fungsi akan menjeda dan menyimpan semua maklumat semasa berjalan dan mengembalikan nilai hasil. Dan teruskan berjalan dari kedudukan semasa pada kali seterusnya kaedah next() dilaksanakan.

Jadi bagaimana untuk mencipta penjana? . yang terakhir Bahagian luar [] dan (). Tetapi penjana sebenarnya tidak membuat senarai nombor, sebaliknya mengembalikan penjana yang "menghasilkan" (menghasilkan) item setiap kali ia dikira. Ungkapan penjana menggunakan "penilaian malas" (penilaian malas, juga diterjemahkan sebagai "penilaian tertunda", saya fikir kaedah panggilan ini mengikut keperluan lebih baik diterjemahkan sebagai malas), dan hanya diberikan apabila mengambil semula (dinilai), jadi ia lebih banyak ingatan cekap apabila senarainya panjang.

Jadi saya tahu cara mencipta penjana, tetapi bagaimana saya melihat elemen di dalamnya?

3. Lintas elemen generator

Menurut pemikiran kami, gelung for digunakan untuk traversal. Sudah tentu, iterator juga disebutkan di atas, jadi bolehkah next() digunakan untuk melintasi? Sudah tentu boleh.

4. Laksanakan penjana dalam bentuk fungsi

Seperti yang dinyatakan di atas, cara paling mudah dan paling mudah untuk mencipta penjana ialah menukar [] dalam penjanaan senarai kepada (). Mengapa tiba-tiba ia dicipta dalam bentuk fungsi? Sebenarnya, generator juga merupakan iterator, tetapi anda hanya boleh mengulangnya sekali sahaja. Ini kerana mereka tidak menyimpan semua nilai dalam ingatan, tetapi menjana nilai semasa runtime. Anda menggunakannya dengan mengulanginya, sama ada dengan gelung "untuk", atau dengan menghantarnya ke mana-mana fungsi atau struktur yang boleh diulang. Dan dalam aplikasi sebenar, kebanyakan penjana dilaksanakan melalui fungsi. Jadi bagaimana kita menciptanya melalui fungsi?

Jangan risau, mari kita lihat contoh ini:

# -*- coding: UTF-8 -*-
gen= (x * x for x in range(10))
print(gen)

Hasil output:

<generator object <genexpr> at 0x0000000002734A40>

Jika kita perlu mengubahnya menjadi penjana, kita hanya perlu menukar cetakan ( i ) untuk menghasilkan i , lihat at it specifically Modified example:

# -*- coding: UTF-8 -*-
gen= (x * x for x in range(10))
for num  in  gen :
print(num)

Output result:

# -*- coding: UTF-8 -*-
def my_function():
    for i in range(10):
        print ( i )
my_function()

Walau bagaimanapun, contoh ini sangat tidak sesuai untuk menggunakan generator dan tidak boleh mengeluarkan ciri-ciri generator The best application of generator should be: anda tidak mahu untuk menggunakan semua penjana pada masa yang sama Sebilangan besar set hasil yang dikira diperuntukkan kepada ingatan, terutamanya jika set hasil juga mengandungi gelung. Kerana ini akan memakan banyak sumber.

Sebagai contoh, berikut adalah penjana yang mengira jujukan Fibonacci:

0
1
2
3
4
5
6
7
8
9

Kesan berlari:

c510424ccec9b78105579250c3f3799.pngAnda lihat, menjalankan parameter seperti ini tidak akan mengatakan terdapat keadaan tersekat, kerana kaedah ini Adakah' t menggunakan terlalu banyak sumber. Di sini, perkara yang paling sukar untuk difahami ialah aliran pelaksanaan penjana dan fungsi adalah berbeza. Fungsi dilaksanakan secara berurutan dan kembali apabila menemui pernyataan pulangan atau baris terakhir pernyataan fungsi. Fungsi yang menjadi penjana dilaksanakan setiap kali next() dipanggil, kembali apabila menemui penyataan hasil dan meneruskan pelaksanaan daripada penyataan hasil pulangan terakhir apabila dilaksanakan semula.

Sebagai contoh, contoh ini:

# -*- coding: UTF-8 -*-
def my_function():
    for i in range(10):
        yield i
print(my_function())

Anda dapat melihat bahawa ganjil bukan fungsi biasa, tetapi penjana semasa pelaksanaan, ia akan terganggu apabila ia menemui hasil, dan pelaksanaan akan diteruskan pada masa akan datang. Selepas melaksanakan hasil 3 kali, tiada lagi hasil untuk dilaksanakan Jika anda terus mencetak cetakan(seterusnya(o)), ralat akan dilaporkan. Jadi ralat biasanya ditangkap dalam fungsi penjana.

5. Cetak segi tiga Yang Hui

Dengan mempelajari penjana, kita boleh terus menggunakan titik pengetahuan penjana untuk mencetak segi tiga Yang Hui:

<generator object my_function at 0x0000000002534A40>

Hasil keluarannya ialah:

rreee
Meneruskan pembelajaran
  • Cadangan kursus
  • Muat turun perisian kursus