class Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
Ini tidak persis sama dengan hal serupa yang berfungsi dalam bahasa lain, dan menggunakan pencarian global alih-alih membatasi akses ke outer_var
. (Jika Anda mengubah objek apa yang Outer
terikat dengan nama , maka kode ini akan menggunakan objek itu saat dijalankan berikutnya.)
Jika Anda malah ingin semua Inner
objek memiliki referensi ke Outer
karena outer_var
sebenarnya adalah atribut instance:
class Outer(object):
def __init__(self):
self.outer_var = 1
def get_inner(self):
return self.Inner(self)
# "self.Inner" is because Inner is a class attribute of this class
# "Outer.Inner" would also work, or move Inner to global scope
# and then just use "Inner"
class Inner(object):
def __init__(self, outer):
self.outer = outer
@property
def inner_var(self):
return self.outer.outer_var
Perhatikan bahwa kelas bersarang agak tidak umum di Python, dan tidak secara otomatis menyiratkan segala jenis hubungan khusus antara kelas. Anda lebih baik tidak bersarang. (Anda masih dapat menyetel atribut kelas Outer
ke Inner
, jika Anda mau.)
Outer
selalu dicari lagi setiap kali Anda melakukannyaInner.inner_var
. Jadi jika Anda mengembalikan namaOuter
ke objek baru,Inner.inner_var
akan mulai mengembalikan objek baru itu.Saya pikir Anda cukup melakukan:
Masalah yang Anda temui adalah karena ini:
Artinya di atas:
badan fungsi adalah blok kode dan metode adalah fungsi, maka nama yang ditentukan dari badan fungsi yang ada dalam definisi kelas tidak meluas ke badan fungsi.
Parafrase ini untuk kasus Anda:
definisi kelas adalah blok kode, maka nama yang ditentukan dari definisi kelas dalam yang ada dalam definisi kelas luar tidak mencakup definisi kelas dalam.
sumber
[a + i for i in range(10)]
berhasil mengikat Ab ke daftar yang diharapkan [42..51].list(a + i for i in range(10))
adalahlist((a + i for i in range(10)))
yang mengatakanlist(a_generator)
. Mereka mengatakan generator diimplementasikan dengan lingkup yang sama dari lingkup fungsi.list(...)
panggilan maupun pemahaman tidak bekerja dengan Python 3. Dokumentasi untuk Py3 juga sedikit berbeda mencerminkan hal ini. Sekarang dikatakan " Ruang lingkup nama yang didefinisikan dalam blok kelas terbatas pada blok kelas; itu tidak meluas ke blok kode metode - ini termasuk pemahaman dan ekspresi generator karena mereka diimplementasikan menggunakan ruang lingkup fungsi. " (Penekanan milik saya ).Anda mungkin lebih baik jika Anda tidak menggunakan kelas bersarang. Jika Anda harus bersarang, coba ini:
Atau nyatakan kedua kelas sebelum menumpuknya:
(Setelah ini Anda bisa
del InnerClass
jika perlu.)sumber
Solusi termudah:
Ini mengharuskan Anda untuk bersikap eksplisit, tetapi tidak membutuhkan banyak usaha.
sumber
Dalam Python, objek yang bisa berubah diteruskan sebagai referensi, sehingga Anda bisa meneruskan referensi kelas luar ke kelas dalam.
sumber
__del__
metode, pengumpul sampah tidak akan dapat menangani siklus referensi, dan objek akan masukgc.garbage
. Kode di atas, sebagaimana adanya, tidak bermasalah. Cara mengatasinya menggunakan referensi yang lemah . Anda dapat membaca dokumentasi di weakref (2.7) atau weakref (3.5)Semua penjelasan dapat ditemukan di Dokumentasi Python Tutorial Python
Untuk kesalahan pertama Anda
<type 'exceptions.NameError'>: name 'outer_var' is not defined
. Penjelasannya adalah:dikutip dari The Python Tutorial 9.4
Untuk kesalahan kedua Anda
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
dikutip dari Tutorial Python 9.3.1
Jadi ketika Anda mencoba
inner_var = Outerclass.outer_var
,Quterclass
itu belum dibuat, itu sebabnyaname 'OuterClass' is not defined
Penjelasan yang lebih rinci tapi membosankan untuk kesalahan pertama Anda:
dikutip dari Learning.Python (5th) .Mark.Lutz
sumber