Saya memiliki situasi seperti ini ...
class Outer(object):
def some_method(self):
# do something
class Inner(object):
def __init__(self):
self.Outer.some_method() # <-- this is the line in question
Bagaimana cara mengakses Outer
metode Inner
kelas dari kelas?
python
scope
nested
inner-classes
T. Stone
sumber
sumber
self.<original_parent_name>
dan mendapatkan kelas aslinya, bukan kelas baru tempat mereka menjadi sub-kelas . Saya berharap orang-orang yang membaca ini dapat memvisualisasikan skenario yang sulit ini dan melihat inti dari pertanyaan seperti ini.Jawaban:
Metode kelas bersarang tidak bisa langsung mengakses atribut instance dari kelas luar.
Perhatikan bahwa tidak selalu terjadi bahwa instance dari kelas luar ada bahkan ketika Anda telah membuat instance dari kelas dalam.
Faktanya, sering kali direkomendasikan untuk tidak menggunakan kelas bersarang, karena penumpukan tidak menyiratkan hubungan tertentu antara kelas dalam dan luar.
sumber
Anda mencoba untuk mengakses contoh kelas Luar, dari contoh kelas dalam. Jadi gunakan saja metode pabrik untuk membuat instance Inner dan meneruskan instance Outer ke sana.
sumber
mungkin aku marah tapi ini nampaknya memang sangat mudah - masalahnya adalah membuat kelas dalammu di dalam metode kelas luar ...
Plus ... "self" hanya digunakan oleh konvensi, jadi Anda dapat melakukan ini:
Mungkin ada keberatan bahwa Anda tidak dapat membuat kelas dalam ini dari luar kelas luar ... tapi ini tidak benar:
kemudian, di suatu tempat bermil-mil jauhnya:
bahkan mendorong perahu keluar sedikit dan memperluas kelas dalam ini (NB untuk mendapatkan super () untuk bekerja Anda harus mengubah tanda tangan kelas dari mooble menjadi "kelas mooble (objek)"
kemudian
mrh1997 mengangkat poin yang menarik tentang warisan non-umum dari kelas dalam yang disampaikan menggunakan teknik ini. Tetapi tampaknya solusinya cukup mudah:
sumber
Apakah Anda bermaksud menggunakan warisan, daripada kelas bertingkat seperti ini? Apa yang Anda lakukan tidak masuk akal dengan Python.
Anda dapat mengakses
Outer
some_method dengan hanya mereferensikanOuter.some_method
di dalam metode kelas dalam, tetapi itu tidak akan bekerja seperti yang Anda harapkan. Misalnya, jika Anda mencoba ini:... Anda akan mendapatkan TypeError saat menginisialisasi
Inner
objek, karenaOuter.some_method
mengharapkan untuk menerima sebuahOuter
instance sebagai argumen pertamanya. (Dalam contoh di atas, pada dasarnya Anda mencoba memanggilsome_method
sebagai metode kelasOuter
.)sumber
Anda dapat dengan mudah mengakses ke kelas luar menggunakan metaclass: setelah pembuatan kelas luar periksa atribut itu dikt untuk kelas apa pun (atau terapkan logika apa pun yang Anda butuhkan - milik saya hanyalah contoh sepele) dan mengatur nilai yang sesuai:
Dengan menggunakan pendekatan ini, Anda dapat dengan mudah mengikat dan merujuk dua kelas satu sama lain.
sumber
Saya telah membuat beberapa kode Python untuk menggunakan kelas luar dari kelas dalam , berdasarkan ide bagus dari jawaban lain untuk pertanyaan ini. Menurut saya ini singkat, sederhana dan mudah dimengerti.
Kode utama, "produksi siap" (tanpa komentar, dll.). Ingatlah untuk mengganti semua nilai dalam tanda kurung siku (misalnya
<x>
) dengan nilai yang diinginkan.Penjelasan cara kerja metode ini (langkah-langkah dasar):
Buat fungsi bernama
_subclass_container
untuk bertindak sebagai pembungkus untuk mengakses variabelself
, referensi ke kelas tingkat yang lebih tinggi (dari kode yang berjalan di dalam fungsi).Buat variabel bernama
_parent_class
yang merupakan referensi ke variabelself
fungsi ini, yang_subclass_container
dapat diakses sub-kelas (hindari konflik nama denganself
variabel lain di subkelas).Kembalikan sub-kelas / sub-kelas sebagai kamus / daftar sehingga kode yang memanggil
_subclass_container
fungsi dapat mengakses sub-kelas di dalamnya.Dalam
__init__
fungsi di dalam kelas tingkat yang lebih tinggi (atau di mana pun dibutuhkan), menerima sub-kelas yang dikembalikan dari fungsi_subclass_container
ke dalam variabelsubclasses
.Tetapkan sub-kelas yang disimpan dalam
subclasses
variabel ke atribut kelas tingkat yang lebih tinggi.Beberapa tip untuk membuat skenario lebih mudah:
Membuat kode untuk menetapkan sub kelas ke kelas tingkat yang lebih tinggi lebih mudah untuk disalin dan digunakan di kelas yang berasal dari kelas tingkat yang lebih tinggi yang
__init__
fungsinya berubah:Sisipkan sebelum baris 12 di kode utama:
Kemudian masukkan ke dalam fungsi ini baris 5-6 (dari kode utama) dan ganti baris 4-7 dengan kode berikut:
Membuat subclass menetapkan ke kelas tingkat yang lebih tinggi mungkin ketika ada banyak / jumlah subclass yang tidak diketahui.
Ganti baris 6 dengan kode berikut:
Contoh skenario di mana solusi ini akan berguna dan di mana nama kelas tingkat yang lebih tinggi seharusnya tidak mungkin didapat:
Sebuah kelas, bernama "a" (
class a:
) dibuat. Ini memiliki subclass yang perlu mengaksesnya (induk). Satu subclass disebut "x1". Di subclass ini, kodea.run_func()
dijalankan.Kemudian kelas lain, bernama "b" dibuat, diturunkan dari kelas "a" (
class b(a):
). Setelah itu, beberapa kode dijalankanb.x1()
(memanggil subfungsi "x1" dari b, sub-kelas turunan). Fungsi ini berjalana.run_func()
, memanggil fungsi "run_func" dari kelas "a", bukan fungsi "run_func" dari induknya, "b" (sebagaimana mestinya), karena fungsi yang didefinisikan di kelas "a" diatur untuk merujuk ke fungsi kelas "a", karena itu adalah induknya.Hal ini akan menyebabkan masalah (misalnya jika fungsi
a.run_func
telah dihapus) dan satu-satunya solusi tanpa menulis ulang kode di kelasa.x1
adalah dengan mendefinisikan kembali sub-kelasx1
dengan kode yang diperbarui untuk semua kelas yang diturunkan dari kelas "a" yang jelas akan sulit dan tidak bernilai. Itu.sumber
Saya menemukan ini .
Tweak untuk menyesuaikan pertanyaan Anda:
Saya yakin Anda entah bagaimana bisa menulis dekorator untuk ini atau sesuatu
terkait: Apa tujuan kelas dalam python?
sumber
Kemungkinan lain:
sumber
Memperluas pemikiran meyakinkan @ tsnorri, bahwa metode luar mungkin metode statis :
Sekarang baris yang dimaksud harus berfungsi pada saat sebenarnya dipanggil.
Baris terakhir dalam kode di atas memberikan kelas Inner metode statis yang merupakan tiruan dari metode statis Luar.
Ini memanfaatkan dua fitur Python, yaitu fungsi objek , dan cakupan tekstual .
... atau kelas saat ini dalam kasus kami. Jadi objek "lokal" dengan definisi kelas Luar (
Inner
dansome_static_method
) dapat dirujuk langsung dalam definisi itu.sumber
Beberapa tahun terlambat ke pesta .... tapi untuk memperluas
@mike rodent
jawaban indah 's, saya telah menyediakan contoh saya sendiri di bawah ini menunjukkan bahwa betapa fleksibel solusinya adalah, dan mengapa itu harus (atau harus telah menjadi) yang diterima menjawab.Python 3.7
Keluaran:
Sekali lagi, jawaban yang bagus, alat peraga untuk Anda mike!
sumber
Itu terlalu sederhana:
Memasukkan:
Keluaran
kelas A func1
kelas B func1
sumber
func1
. Dan, sama lucunya, Anda membuatA
di dalam konstruktorB
, yang sama sekali BUKANA
objek kelas luar tertentuB
.