在多重继承当中,派生的类中,表面上看基类排列的顺序不同,会导致输出不同,当然实质上是调用的类方法不同,更实质原因是搜索方法的方式不同
__author__ = 'LiHui' class MyBook(object): def __init__(self): print 'MyBook __init__' def foo(self): print 'MyBook foo' class MyCook(object): def __init__(self): print 'MyCook __init__' def foo(self): print 'MyCook foo' class MyCookBook(MyBook, MyCook): def __init__(self): print 'MyCookBook __init__' class MyStoryBook(MyCook, MyBook): def __init__(self): print 'MyStoryBook __init__' if __name__ == '__main__': cookbook = MyCookBook() cookbook.foo() storybook = MyStoryBook() storybook.foo()
这里输出结果,很简单
MyCookBook __init__ MyBook foo MyStoryBook __init__ MyCook foo
cookbook和storybook调用foo方法时,分别搜索到了基类MyBook和MyCook里的foo方法,从而打印信息,这个例子比较easy
下面这个改进版,信息量就比较大了,注意这里class都是继承object,为新式类
__author__ = 'LiHui' class MyBook(object): def __init__(self): print 'MyBook __init__' def foo(self): print 'MyBook foo' class MyCook(object): def __init__(self): print 'MyCook __init__' def fun(self): print 'MyCook fun' class MyCookBook(MyBook, MyCook): def __init__(self): print 'MyCookBook __init__' class MyStoryBook(MyBook, MyCook): def __init__(self): print 'MyStoryBook __init__' def fun(self): print 'MyStoryBook fun' class MyLastBook(MyCookBook, MyStoryBook): pass if __name__ == '__main__': lastbook = MyLastBook() lastbook.foo() lastbook.fun()
输出结果为:
MyCookBook __init__ MyBook foo MyStoryBook fun
1:打印了MyCookBook __init__,原因是MyLastBook里面没有__init__,因此继承其第一个基类MyCookBook的时候,会调用基类的__init__方法,因此会打印这一行,而MyStoryBook的却没有打印,说明根本就调用这个类的构造器;而后面的MyBook和MyCook却没有打印,是子类MyCookBook的__init__将他们的给覆盖掉了
2:搜索调用顺序
MyLastBook =》 MyCookBook =》 MyBook =》 foo
MyLastBook =》 MyStoryBook =》 fun
也就是说这种情况下,搜索的方式是广度优先的原则,然后再从左到右搜索其它基类,依旧广度优先;更直接一点就是,派生出来的子类,先搜索参数里第一个基类,然后第二个基类,所有基类搜索完毕没找到,再搜索第一个基类的第一个基类,接着第一个基类的第二个基类,如此循环
下面会将基类的object给去掉,这是一种旧式类定义
__author__ = 'LiHui' class MyBook(): def __init__(self): print 'MyBook __init__' def foo(self): print 'MyBook foo' class MyCook(): def __init__(self): print 'MyCook __init__' def fun(self): print 'MyCook fun' class MyCookBook(MyBook, MyCook): def __init__(self): print 'MyCookBook __init__' class MyStoryBook(MyBook, MyCook): def __init__(self): print 'MyStoryBook __init__' def fun(self): print 'MyStoryBook fun' class MyLastBook(MyCookBook, MyStoryBook): pass if __name__ == '__main__': lastbook = MyLastBook() lastbook.foo() lastbook.fun()
除了去掉了object之外,没有任何改变
MyCookBook __init__ MyBook foo MyCook fun
这里的搜索顺序变成了:
MyLastBook =》 MyCookBook =》 MyBook =》 foo
MyLastBook =》 MyCookBook =》 MyBook =》 MyCook =》 fun
也就是说这种情况下,搜索的方式是深度优先的原则,然后再从左到右搜索其它基类,依旧深度优先;更直接一点就是,派生出来的子类,先搜索参数里第一个基类,然后深度遍历完第一个基类,接着搜索第二个基类,深度遍历完,直到搜索完所有基类,以找到对应的方法
这就是旧式类和新式类的区别,遍历搜索方式不同,旧式是深度优先,而新式类是广度优先