Jadi saya mengikuti Python's Super Dianggap Berbahaya , dan pergi untuk menguji contohnya.
Namun, Contoh 1-3 , yang seharusnya menunjukkan cara pemanggilan yang benar super
saat menangani __init__
metode yang mengharapkan argumen berbeda, tidak berhasil.
Inilah yang saya dapatkan:
~ $ python example1-3.py
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
File "Download/example1-3.py", line 27, in <module>
E(arg=10)
File "Download/example1-3.py", line 24, in __init__
super(E, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 14, in __init__
super(C, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 4, in __init__
super(A, self).__init__(*args, **kwargs)
File "Download/example1-3.py", line 19, in __init__
super(D, self).__init__(arg, *args, **kwargs)
File "Download/example1-3.py", line 9, in __init__
super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters
Tampaknya itu object
sendiri melanggar salah satu praktik terbaik yang disebutkan dalam dokumen, yaitu metode yang digunakan super
harus menerima *args
dan **kwargs
.
Sekarang, jelas Tuan Knight mengharapkan contohnya bekerja, jadi apakah ini sesuatu yang telah diubah dalam versi terbaru Python? Saya memeriksa 2.6 dan 2.7, dan gagal pada keduanya.
Jadi bagaimana cara yang benar untuk mengatasi masalah ini?
object
, dan itu membuat yakin untuk panggilanobject
's__init__
benar.__init__
onobject
mengabaikan parameter apa pun secara diam-diam pada Python 2.5. Ini berubah di Python 2.6.Jawaban:
Terkadang dua kelas mungkin memiliki beberapa nama parameter yang sama. Dalam hal ini, Anda tidak dapat mengeluarkan pasangan nilai kunci
**kwargs
atau menghapusnya*args
. Sebagai gantinya, Anda dapat menentukanBase
kelas yang tidak sepertiobject
, menyerap / mengabaikan argumen:hasil
Perhatikan bahwa untuk bekerja,
Base
harus kelas kedua dari belakang di MRO.sumber
Base
meneleponsuper(Base, self).__init__()
?Base
harus datang di akhir MRO (kecualiobject
). Meneleponobject.__init__
tidak berarti apa-apa, jadi tidak apa-apa untuk tidak meneleponsuper(Base, self).__init__()
. Faktanya, saya pikir mungkin lebih jelas untuk tidak memasukkansuper(Base, self).__init__()
untuk pulang ke titik yangBase
merupakan akhir baris.Jika Anda akan memiliki banyak pewarisan (itulah yang terjadi di sini) saya sarankan Anda untuk meneruskan semua parameter menggunakan
**kwargs
, dan kemudianpop
mereka segera setelah Anda menggunakannya (kecuali Anda membutuhkannya di kelas atas).Ini adalah cara termudah untuk memecahkan masalah semacam itu.
sumber
Seperti yang dijelaskan dalam Python super () dianggap super , salah satu caranya adalah dengan membuat kelas memakan argumen yang diperlukan, dan meneruskan sisanya. Jadi, ketika rantai panggilan mencapai
object
, semua argumen telah dimakan, danobject.__init__
akan dipanggil tanpa argumen (seperti yang diharapkan). Jadi kode Anda akan terlihat seperti ini:sumber
E(arg = 10)
? Saya tidak suka metode ini, saya perlu mengetahui MRO terlebih dahulu untuk menggunakannya. Metode lain di mana saya menulis "kelas root" yang diwarisi dariobject
tampaknya jauh lebih bersih.super
, jadi pendekatan ini mungkin memang agak teoretis.