Ini dirinci dengan jumlah detail yang masuk akal oleh Guido sendiri dalam posting blognya Metode Resolution Order (termasuk dua upaya sebelumnya).
Dalam contoh Anda, Third()
akan menelepon First.__init__
. Python mencari setiap atribut dalam orangtua kelas karena mereka terdaftar kiri ke kanan. Dalam hal ini, kami sedang mencari __init__
. Jadi, jika Anda mendefinisikan
class Third(First, Second):
...
Python akan mulai dengan melihat First
, dan, jika First
tidak memiliki atribut, maka akan terlihat Second
.
Situasi ini menjadi lebih kompleks ketika warisan mulai melintasi jalur (misalnya jika First
diwarisi dari Second
). Bacalah tautan di atas untuk detail lebih lanjut, tetapi, singkatnya, Python akan mencoba mempertahankan urutan di mana setiap kelas muncul di daftar warisan, dimulai dengan kelas anak itu sendiri.
Jadi, misalnya, jika Anda punya:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First):
def __init__(self):
print "third"
class Fourth(Second, Third):
def __init__(self):
super(Fourth, self).__init__()
print "that's it"
MRO akan menjadi [Fourth, Second, Third, First].
By the way: jika Python tidak dapat menemukan urutan resolusi metode yang koheren, itu akan menimbulkan pengecualian, bukannya kembali ke perilaku yang mungkin mengejutkan pengguna.
Diedit untuk menambahkan contoh MRO yang ambigu:
class First(object):
def __init__(self):
print "first"
class Second(First):
def __init__(self):
print "second"
class Third(First, Second):
def __init__(self):
print "third"
Haruskah Third
MRO menjadi [First, Second]
atau [Second, First]
? Tidak ada harapan yang jelas, dan Python akan meningkatkan kesalahan:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution order (MRO) for bases Second, First
Sunting: Saya melihat beberapa orang berpendapat bahwa contoh di atas tidak memiliki super()
panggilan, jadi izinkan saya menjelaskan: Inti dari contoh adalah untuk menunjukkan bagaimana MRO dibangun. Mereka tidak dimaksudkan untuk mencetak "first \ nsecond \ third" atau apa pun. Anda dapat - dan harus, tentu saja, bermain-main dengan contoh ini, menambahkan super()
panggilan, melihat apa yang terjadi, dan mendapatkan pemahaman yang lebih dalam tentang model pewarisan Python. Tetapi tujuan saya di sini adalah untuk membuatnya tetap sederhana dan menunjukkan bagaimana MRO dibangun. Dan itu dibangun seperti yang saya jelaskan:
>>> Fourth.__mro__
(<class '__main__.Fourth'>,
<class '__main__.Second'>, <class '__main__.Third'>,
<class '__main__.First'>,
<type 'object'>)
super()
ada gunanya. Saya tidak akan merekomendasikan menggunakannya dengan kelas menggunakan pewarisan linear, di mana itu hanya overhead yang tidak berguna.