1. 程式人生 > >Python小技巧之——基類初始化

Python小技巧之——基類初始化

子類__init__初始化時,如果要對基類進行初始化,大家都知道可以用super:

>>> class base(object):
	def __init__(self):
		print('base init')

		
>>> class derived(base):
	def __init__(self):
		print('derived init')
		super(derived, self).__init__()

		
>>> obj=derived()
derived init
base init

以上是最簡單的直接繼承用法,那如果是多繼承會是什麼情況呢?

>>> class base1(object):
	def __init__(self):
		print('base1 init')

		
>>> class base2(object):
	def __init__(self):
		print('base2 init')

		
>>> class derived(base1, base2):
	def __init__(self):
		print('derived init')
		super(derived, self).__init__()

		
>>> obj=derived()
derived init
base1 init

從上面的結果可以看出,通過super的方式呼叫基類__init__實際只調用了第一個繼承基類base1的__init__,而沒有呼叫第二個基類的__init__。

這個就涉及到python類的MRO了,即Method Resolution Order。

看看derived類的MRO:

>>> help(derived)
Help on class derived in module __main__:

class derived(base1, base2)
 |  Method resolution order:
 |      derived
 |      base1
 |      base2
 |      __builtin__.object
上面的MRO顯示了,尋找基類的方法會先查詢base1,然後再找base2,所以前面的例子呼叫了base1的__init__。

按照這種思路,那如果base1沒有定義__init__,是不是就該呼叫base2的__init__了呢?

我們來驗證一下:

>>> class base1(object):
	pass

>>> class base2(object):
	def __init__(self):
		print('base2 init')

		
>>> class derived(base1, base2):
	def __init__(self):
		print('derived init')
		super(derived, self).__init__()

		
>>> obj=derived()
derived init
base2 init
確實如此,呼叫了base2的__init__。

如果不想受到MRO的影響,需要指定呼叫某些基類的__init__怎麼辦呢?

可以直接使用類名進行修飾:

>>> class derived(base1, base2):
	def __init__(self):
		print('derived init')
		base2.__init__(self)
		base1.__init__(self)

		
>>> obj=derived()
derived init
base2 init
base1 init
通過這種方式可以自行定製基類的初始化。