Pertanyaan Fungsi lokal dengan Python


Dalam kode Python berikut, saya mendapatkan UnboundLocalError. Seperti yang saya pahami, fungsi lokal berbagi variabel lokal dari fungsi yang mengandung, tetapi ini hampir tidak terjadi di sini. Saya menyadari itu a adalah nilai yang tidak dapat diubah dalam konteks ini, tetapi itu seharusnya tidak menjadi masalah.

def outer():
    a = 0
    def inner():
        a += 1
    inner()
outer()

Tampaknya fungsi dalam telah menerima salinan dari semua referensi dalam fungsi induk, karena saya tidak mendapatkan UnboundLocalError kecuali jika nilai a dibungkus dalam jenis yang bisa berubah.

Apakah seseorang dapat mengklarifikasi perilaku di sini, dan mengarahkan saya ke dokumentasi Python yang sesuai untuk hal ini?


32
2017-09-12 04:45


asal


Jawaban:


Saya yakin Anda benar dalam melihat ini sebagai masalah "berubah-ubah". Sementara kode yang Anda posting tidak melempar "UnboundLocalError", kode berikut tidak:

def outer():
    a = 0
    def inner():
        print a
    inner()
outer()

Python tidak mengizinkan Anda menetapkan kembali nilai variabel dari luar lingkup dalam ruang lingkup (kecuali Anda menggunakan kata kunci "global", yang tidak berlaku dalam kasus ini).

Lihat bagian bawah dokumentasi "kelas" dalam dokumentasi Python 2.6.2 ini:

9.2. Python Scopes dan Namespaces

[...] Jika sebuah nama dinyatakan global, maka semua referensi dan tugas pergi   langsung ke ruang tengah yang berisi nama global modul.   Jika tidak, semua variabel yang ditemukan di luar ruang lingkup paling dalam adalah   read-only (usaha untuk menulis ke variabel seperti itu hanya akan membuat a   variabel lokal baru di ruang lingkup paling dalam, meninggalkan yang identik   bernama variabel luar tidak berubah).

"UnboundLocalError" Anda adalah karena fungsi Anda benar-benar mendeklarasikan variabel baru yang disebut "a" dan kemudian segera mencoba melakukan operasi "+ =" di atasnya, tetapi ini gagal karena "a" belum memiliki nilai. (Lihat "a + = 1" sebagai "a = a + 1" dan Anda dapat melihat masalah jika "a" tidak terdefinisi).

Secara umum, jika Anda ingin memodifikasi "a", cara orang biasanya mengatasinya adalah dengan menggunakan tipe yang bisa berubah untuk meneruskan "a" sekitar (seperti daftar atau kamus). Anda dapat memodifikasi "a" melalui isi dari jenis yang bisa berubah (seperti yang mungkin Anda perhatikan dalam pengujian Anda dengan pengaturan ini).

Semoga itu membantu!


30
2017-09-12 04:54



Coba ikat variabel sebagai argumen.

def outer():
    a = 0
    def inner(a=a):
        a += 1

    inner()

outer()

Saya akan mencoba dan menggali dokumen yang sesuai.

sunting

Karena Anda ingin fungsi bagian dalam memiliki efek samping pada lingkup luar, maka Anda perlu menggunakan datatype yang bisa berubah seperti daftar. Bilangan bulat dan string tidak dapat diubah.

def outer():
    a = [0]
    def inner():
        a[0] += 1
    inner()
    print a[0]
outer()

8
2017-09-12 04:55



Anda harus menentukan variabel Anda sebagai nonlokal untuk mempertahankan statusnya dalam penutupan, sehingga definisi harus seperti ini

def outer():
a = 0
def inner():
    nonlocal a
    a += 1
inner()

8
2018-03-11 08:41