Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Analisis skop penutupan dan lambda dalam Python

Analisis skop penutupan dan lambda dalam Python

WBOY
WBOYke hadapan
2022-07-22 16:37:122573semak imbas

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.

Analisis skop penutupan dan lambda dalam Python

[Cadangan berkaitan: Tutorial video Python3 ]

Skop penutupan Python dan lambda

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)

Perangkap dalam python (penutupan dan lambda)

Mari kita lihat buah berangan pertama

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:

  • Dalam python3, penapis( ) fungsi mengembalikan iterator. Oleh itu, ia sebenarnya tidak dilaksanakan, tetapi dilaksanakan setiap kali ia dipanggil (senarai nilai yang dikembalikan oleh filter() dalam python2 tidak mempunyai fenomena ini)
  • Apabila pencetakan dilaksanakan selepas traversal , gelung kini dilaksanakan Fungsi, masalah yang sama seperti berangan di atas Pembolehubah i menggunakan nilai apabila ia dipanggil kali terakhir Berangan di atas adalah berangan di atas menggunakan nilai skop terbenam, dan berangan ini menggunakan nilai global i

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!

Kenyataan:
Artikel ini dikembalikan pada:jb51.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam