Baru-baru ini saya mulai bermain-main dengan Python dan saya menemukan sesuatu yang aneh dalam cara penutupan. Pertimbangkan kode berikut:
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
Itu membangun array sederhana fungsi yang mengambil input tunggal dan mengembalikan input yang ditambahkan oleh angka. Fungsi-fungsi dibangun dalam forloop di mana iterator iberjalan dari 0ke 3. Untuk masing-masing angka-angka ini lambdafungsi dibuat yang menangkap idan menambahkannya ke input fungsi. Baris terakhir memanggil lambdafungsi kedua dengan 3sebagai parameter. Yang mengejutkan saya, hasilnya adalah 6.
Saya mengharapkan sebuah 4. Alasan saya adalah: dalam Python semuanya adalah objek dan karenanya setiap variabel adalah penunjuk yang penting. Saat membuat lambdaclosure for i, saya berharap untuk menyimpan pointer ke objek integer yang saat ini ditunjuk oleh i. Itu berarti bahwa ketika imenetapkan objek integer baru itu seharusnya tidak mempengaruhi penutupan yang dibuat sebelumnya. Sayangnya, memeriksa addersarray di dalam debugger menunjukkan hal itu. Semua lambdafungsi mengacu pada nilai terakhir i, 3yang mengakibatkan adders[1](3)kembali 6.
Yang membuat saya bertanya-tanya tentang hal berikut:
- Apa tepatnya yang ditangkap penutup?
- Apa cara paling elegan untuk meyakinkan
lambdafungsi untuk menangkap nilai saat iniidengan cara yang tidak akan terpengaruh ketikaimengubah nilainya?
imeninggalkan namespace?
print itidak akan berhasil setelah loop. Tapi saya mengujinya sendiri dan sekarang saya mengerti maksud Anda - itu berhasil. Saya tidak tahu bahwa variabel loop tetap setelah loop body dengan python.
if, with, trydll