Rumah > Artikel > pembangunan bahagian belakang > Analisis skop penutupan dan lambda dalam Python
Artikel ini membawakan anda pengetahuan yang berkaitan tentang Python terutamanya mengatur isu berkaitan tentang skop lambda, serta kandungan yang berkaitan tentang penutupan dalam Python membantu semua orang.
[Cadangan berkaitan: Tutorial video Python3 ]
Kaedah Penulisan lambda
def fun(): for i in range(3): yield lambda x : x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
Kaedah penulisan penutup
def fun(): result = [] for i in range(3): def demo(x): return x * i result.append(demo) return result f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
Hasil kedua-dua kaedah penulisan di atas ialah 2, 4, 6. Mengikut idea asal, hasilnya hendaklah 0, 2, 6.
Punca masalah:
Masalahnya terletak pada peraturan carian pembolehubah python, LEGB (tempatan, tertutup, global, bulitin dalam contoh di atas, i ialah dalam skop Penutupan (melampirkan), dan penutupan Python adalah terikat lewat Nilai pembolehubah yang saya gunakan dalam penutupan ditemui apabila fungsi dalaman dipanggil.
Penyelesaian
Tukar skop penutupan kepada skop setempat
kaedah penulisan lambda
def fun(): for i in range(3): yield lambda x, i = i: x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
kaedah penulisan penutupan
def fun(): result = [] for i in range(3): def demo(x, i=i): return x * i result.append(demo) return result f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
Hasil keluaran di atas ialah 0, 2, 6
Situasi lain:
def fun(): for i in range(3): yield lambda x : x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3))
Hasil keluaran masih 2, 4, 6
Punca masalah
Penjana (atau iterator) yang dikembalikan oleh kaedah fun() sebenarnya tidak dilaksanakan, tetapi dilaksanakan setiap kali ia dipanggil.
Apabila pencetakan dilakukan selepas traversal, pembolehubah i menggunakan nilai panggilan terakhir. Jika lambda dianggap sebagai kaedah penutupan, nilai pembolehubah i masih dalam skop penutupan (tiada setempat)
def create(): return [lambda x:i*x for i in range(5)] for i in create(): print(i(2))
Keputusan:
8
8
8
8
8
Nilai pulangan bagi fungsi cipta ialah senarai, dan setiap elemen senarai ialah fungsi - fungsi yang mendarabkan parameter input x dengan berbilang i. Keputusan yang dijangkakan ialah 0, 2, 4, 6, 8. Tetapi keputusannya ialah 5 dan 8, yang tidak dijangka.
Memandangkan lambda sering digunakan apabila perangkap ini berlaku, anda mungkin fikir ia adalah masalah dengan lambda, tetapi lambda menyatakan keengganannya untuk disalahkan. Intipati masalah terletak pada peraturan carian atribut dalam python, LEGB (local, enclosing, global, bulitin Dalam contoh di atas, i berada dalam skop penutupan (melampirkan), dan penutupan Python adalah pengikatan lewat nilai pembolehubah yang digunakan dalam penutupan ditanya apabila fungsi dalaman dipanggil
Penyelesaiannya juga sangat mudah, iaitu menukar skop penutupan kepada skop setempat.
def create(): return [lambda x, i=i:i*x for i in range(5)] for i in create(): print(i(2))
Cara penulisan lain:
def create(): a = [] for i in range(5): def demo(x, i=i): return x*i a.append(demo) return a for i in create(): print(i(2))
Dua cara penulisan di atas adalah sama
Hasilnya:
0
2
4
6
8
Satu lagi buah berangan dengan masalah yang sama
Kodnya sangat mudah: (Penafian: masalah python3)
nums = range(2,20) for i in nums: nums = filter(lambda x: x==i or x%i, nums) print(list(nums))
Keputusan:
[2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13 , 14, 15, 16, 17, 18, 19]
Begitu juga mengikut logik biasa, hasilnya hendaklah:
[2 , 3, 5, 7, 11 , 13, 17, 19]
Punca masalah:
Kod diubah suai:
nums = range(2,20) for i in nums: nums = filter(lambda x,i=i: x==i or x%i, nums) print(list(nums))
Keputusan:
[2, 3, 5, 7, 11, 13, 17, 19]
[Pengesyoran berkaitan: Tutorial video Python3]
Atas ialah kandungan terperinci Analisis skop penutupan dan lambda dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!