经典类与新式类的继承顺序
经典类与新式类的继承顺序--两种不同的继承策略。
构造函数(初始化)__init__(self): 的继承策略,就是找哪个__init__(self)的问题
当实例本身有__init__(self) 的时候,会先执行自己的)__init__(self) 函数。
当实例本身没有__init__(self)的时候,它会去找父类中的)__init__(self)函数,此时有2种
继承策略,一种是深度优先,一种是广度优先。
我们看上面的图,先放两句概念上来吓唬吓唬你:
- 当类是经典类时,多继承情况下,会按照深度优先方式查找
- 当类是新式类时,多继承情况下,会按照广度优先方式查找
那么什么是经典类和新式类呢?简而言之,继承自object的类就叫做新式类,object类是python提供的,现在我们还不需要管它从哪里来,因为让类中的很多操作变得更合理了,我们以后记着就这么写就对了。注:下面小伙伴提到,python3.X版本中的类继承默认就是广度优先。
下面来说广度优先和深度优先,首先,B和C两个类都必须继承自D,A类又继承自B、C,就是针对这种情况,没有为什么。。。背下来!我们对应起来看,这里的基类D就是上例中的classmate,BC就是pythoner和female,A则对应fe_pythoner类。
经典类中:当我们这样写:fe_pythoner(pythoner,female),对象调用方法的时候,会先在fe_pythoner里面找,然后依次去找pythoner、classmate、最后再找female。如果找到了,就会执行,并且不再继续找下去了。所以我们刚刚在左侧举出得栗子中它先找到了classmate中的drink方法,才打印出了同样的内容。这就是深度优先。
新式类中:当我们这样写:fe_pythoner(pythoner,female),对象调用方法的时候,会先在fe_pythoner里面找,然后依次去找pythoner、female、最后再找classmate。如果找到了,就会执行,并且不再继续找下去了。所以我们刚刚在右侧举得栗子中它先找到了female、或male中的drink方法,就打印了不同的内容。这就是广度优先。
class classmate(object): def __init__(self,name): self.name = name def eat(self): print '%s is eating.'%self.name def drink(self): print '%s is drinking'%self.name class female(classmate): def drink(self): print '%s drink orange juice'%self.name class male(classmate): def drink(self): print '%s drink alcohol'%self.name class pythoner(classmate): def occupation(self): print '%s is a pythoner.'%self.name class fe_pythoner(pythoner,female): pass class male_pythoner(pythoner,male): pass eva = fe_pythoner('eva') eva.drink() sweet = male_pythoner('sweet') sweet.drink() example Code
如果上面那些你通通没搞清楚,也没关系,在继承的时候可以直接把female类写在前面 fe_pythoner(female,pythoner),这么一来不管怎么样,都是先找female了。
总结:python2的经典类是按照深度优先来继承的,新式类( 包含object字样的) 是按照广度优先来继承的。
python3 经典类和新式类都是统一按照广度优先来继承的。