浅谈Python中的继承
继承
Python中所有的类都是object类的子类,而object继承自type
继承分为接口继承和实现继承
接口继承:使用父类的接口名,子类重写这个方法。尽可能的继承接口类,在子类中实现方法,鼓励对接口类的多继承,这样遵循接口隔离原则,有利于归一化设计,不提倡对抽象类进行多继承
实现继承:子类不需要实现任何东西,直接使用父类接口和实现会增强代码的耦合性,不推荐使用。
一些细节
类继承最终要被实例化,我们多数时候使用的还是对象而不是类。因此我们还是来一点点看继~
继承的过程
承仅仅是一种代码复用的手段,并不会讲代码全部的加载到子类的空间中,方法依然属于父类。下面的例子能看到,Cat.func依然是Animal的,更近一步的理解,func也仅仅是func,它只是被绑定到了类Animal上而已,类只是能帮我们找到这个函数,子类通过父类找到这个函数就完了~。
classAnimal(object): deffunc(self): print("Animal.func") classDog(Animal): deffunc(self): print('Dog.func') classCat(Animal): """Nofunc~""" print(Animal.func)#print(Cat.func)# print(Dog.func)#
实例化的过程
实例化过程中属性和方法并不会出现在实例的空间里。它们依然属于类本身,对象也只是能找到他们,然后调用他们。但是当修改对象的属性时,会在对象的空间中创建同名的属性。这是属于对象的属性。复杂的继承其本质也是一样的。
classAnimal(object): deftell(self): print('self.name:%sAnimal.name%s'%(id(self.name),id(Animal.name))) name='Animal' classCat(Animal): """Nofunc~""" deftell(self): super().tell() print('self.name%sCat.name%s'%(id(self.name),id(Cat.name))) cat=Cat() cat.tell() cat.name='django' cat.tell() #self.name:4473398472Animal.name4473398472 #self.name4473398472Cat.name4473398472 #self.name:4474859736Animal.name4473398472 #self.name4474859736Cat.name4473398472
单继承
越靠近本类的方法会覆盖祖辈的方法,这叫方法的覆盖或重写原理是Python的属性检索机制从内层命名空间往外查询
classMyClass(object): """ Asimpleexampleclass """ MyClassName='MyClass' name='MyClass' deffunc(self): print("Thisis{}".format(self.__class__.name)) defget_name(self): print(self.name) classMySonClass(MyClass): MySonClass='MySonClass' name='MySonClass'#属性的重写 defget_name(self): super().get_name() print('我重写了父类的get_name方法,上面是父类的方法,我来自子类!') person1=MyClass() person2=MySonClass() person1.func() person2.func()#方法的实现继承自己没有,会直接调用父类的方法。但是使用的属性还是自己的。 print('*'*40) person1.get_name() person2.get_name()#方法的接口继承,在子类中重写了这个方法。 #结果 #------------------------------ #ThisisMyClass #ThisisMySonClass #**************************************** #MyClass #MySonClass #我重写了父类的get_name方法,上面是父类的方法,我来自子类!
多继承
就形式上来说,类的继承列表可以是一个,也可以是多个,当继承列表只有一个类时,也就是只有一个父类时,称为单继承,大于一个类,就称为多继承。
新式类的继承方式为广度优先继承经典类的继承方式为深度优先继承。
类继承的顺序可以使用类的__mro__方法查看。
钻石继承
classA(object): m='a' classB(A): m='b' classC(A): m='c' classD(B,C): #m='d' pass x=D() print(x.m) #D的实例化对象如果获取m属性会优先的寻找自己的命名空间,查找顺序为D->B->C->A
super()方法
语法super(类,实例化对象).父类的方法
当super()方法在类的内部使用时候,甚至不需要任何的参数
当在多继承中使用super()方法的时候执行的不再是父类的方法了而是和mro中上一级的方法
super()为了解决多继承中,初始化方法被重复调用的问题。(当使用类名.方法名的时候)
当使用super()方法执行“父类”(__mro__方法的上一个类)的方法
#钻石继承中的重复调用问题 #注意继承的查找顺序~使用super()将按照mro顺序执行 classGrand(object): def__init__(self,name): self.name=name print("classGrand") classSonLeft(Grand): def__init__(self,age,name): self.age=age Grand.__init__(self,name)#注释调跑一跑看一看 #super().__init__(age,name) print("classSonLeft") classSonRight(Grand): def__init__(self,gender,name): self.gender=gender Grand.__init__(self,name)#注释调跑一跑看一看 #super().__init__(name) print("classSonRight") classGrandSon(SonLeft,SonRight): def__init__(self,name,age,gender): #super().__init__(age,name) SonLeft.__init__(self,age,name)#注释调跑一跑看一看 SonRight.__init__(self,gender,name)#注释调跑一跑看一看 self.gender=gender grand_son=GrandSon("Monkey",18,"男")
以上就是浅谈Python中的继承的详细内容,更多关于Python继承的资料请关注毛票票其它相关文章!