比较官方的说法就是:
继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B, 就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。 继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。 在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法, 即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。
字面意思就是:子承父业,合法继承家产,就是如果你是独生子,而且你也很孝顺,不出意外, 你会继承你父母所有家产,他们的所有财产都会由你使用(败家子儿除外)。
抽象即抽取类似或者说比较像的部分。
抽象分成两个层次:
1.将雷昂纳多和王思聪这俩对象比较像的部分抽取成类;
2.将人,猪,狗这三个类比较像的部分抽取成父类。
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
class Animal: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex class People(Animal): def walk(self): print("People [%s] is walking..." % self.name) class Pig(Animal): def eat(self): print("Pig [%s] is eating..." % self.name) class Dog(Animal): def eat(self): print("Dog [%s] is eating..." % self.name) person = People("Alex",25,"Male") pig = Pig("Mjj",4,"公") dog = Dog("毛毛",3,"母") person.walk() pig.eat() dog.eat()
继承的有点也是显而易见的:
1,增加了类的耦合性。
2,减少了重复代码。
3,使得代码更加规范化,合理化。
就向上面的例子:
Aminal 叫做父类,基类,超类。 Person Pig Dog: 子类,派生类。 继承:可以分单继承,多继承。
class Animal: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print("[%s] is eating..."%self.name) class People(Animal): def walk(self): print("People [%s] is walking..." % self.name) class Pig(Animal): def eat(self): # 对父类的方法进行了重构 print("Pig [%s] is eating..." % self.name) person = People("Alex",25,"Male") pig = Pig("Mjj",4,"公") person.walk() person.eat() # 继承自父类的eat方法 pig.eat()
父类.func(子类对象,其他参数)
class Animal: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): print("[%s] is eating..."%self.name) class People(Animal): def __init__(self,name,age,sex,race): Animal.__init__(self,name,age,sex) # 先执行父类方法 self.race = race # 再加上子类的属性 print("初始化了一个人....") def walk(self): print("People [%s] is walking..." % self.name)
利用super,super().func(参数)
class People(Animal): def __init__(self,name,age,sex,race): #Animal.__init__(self,name,age,sex) # 先执行父类方法 super(People,self).__init__(name,age,sex) #super().__init__(name,age,sex) # 跟上面这行super语法的效果一样,一般用这种写法的多 self.race = race # 再加上子类的属性 print("初始化了一个人....")
class ShenXian: """神仙类""" def fly(self): print("神仙都会飞...") class Monkey: def eat_peach(self): print("猴子都喜欢吃桃子...") class MonkeyKing(ShenXian,Monkey): def play_goden_stick(self): print("孙悟空玩金箍棒...") sxz = MonkeyKing() sxz.eat_peach() sxz.fly() sxz.play_goden_stick()
此时, 孙悟空是一只猴子, 同时也是一个神仙. 那孙悟空继承了这两个类. 孙悟空自然就可以执行这两个类中的方法. 多继承用起来简单. 也很好理解.
假如在继承的多个类里出现了重名的方法怎么办呢? 如下:
class ShenXian: """神仙类""" def fly(self): print("神仙都会飞...") def fight(self): print("神仙在打架...") class Monkey: def eat_peach(self): print("猴子都喜欢吃桃子...") def fight(self): print("猴子在打架...") class MonkeyKing(ShenXian,Monkey): def play_goden_stick(self): print("孙悟空玩金箍棒...") sxz = MonkeyKing() # sxz.eat_peach() # sxz.fly() # sxz.play_goden_stick() sxz.fight()
调用sxz.fight()你说会打印哪个呢?
根据执行结果,我们得知,多继承的顺序是按参数 MonkeyKing(ShenXian,Monkey)从左到右,不信你可以自己换一下位置试试。
真的是从左到右么? 如果继承的父类又继承爷爷类,并且还重名了呢?
class ShenXianBase: def fight(self): print("神仙祖宗在打架....") class MonkeyBase: def fight(self): print("猿猴在打架....") class ShenXian(ShenXianBase): """神仙类""" def fly(self): print("神仙都会飞...") #def fight(self): # print("神仙在打架...") class Monkey(MonkeyBase): def eat_peach(self): print("猴子都喜欢吃桃子...") def fight(self): print("猴子在打架...") class MonkeyKing(ShenXian,Monkey): def play_goden_stick(self): print("孙悟空玩金箍棒...") sxz = MonkeyKing() sxz.fight()
此时,若把ShenXian类里的fight注释掉,你说sxz.fight()会打印哪个? 是引用Monkey里的fight呢,还是ShenXianBase里的fight呢?
输出: 神仙祖宗在打架....
这个查找顺序是按什么规则呢?
在Python 中,有2种类的写法, 不同写法的采用的继承顺序不同
class A: # 经典类 pass class B(object): # 新式类 pass
在python 2中,经典类采用的是深度优先查找法, 新式类采用的是广度优先
在python 3中,无论是经典类,还是新式类,都是按广度优先查找
Python 2.x中默认都是经典类,只有显式继承了object才是新式类 Python 3.x中默认都是新式类,不必显式的继承object
*之所以在python3中全改成了广度优先,是因为用深度优先在某些特殊情况下,会出现bug.
亲,我没说瞎话,在下面这种条件下,你发现继承的顺序你可能都理解不了了。
class A: def test(self): print('from A') class B(A): # def test(self): # print('from B') pass class B2: def test(self): print('from B2') class C(A): def test(self): print('from C') class C2: def test(self): print('from C2') class D(B,B2): # def test(self): # print('from D') pass class E(C,C2): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) # 打印类的继承顺序
输出: from E (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.B2'>, <class '__main__.C2'>, <class 'object'>)
这个C3算法呢,对现阶段的你,估计不太好理解,所以我也不打算讲, 不过确实也不太重要。 因为很少有人把继承写的这么复杂。 你以后常遇到的也就像下图这种水平的了,
像这种,你就按深度优先来找顺序就可以(因为像这种简单的多继承,c3算出来跟深度优先效果一样)。
C3算法实现原理深入参考:
Python多重继承排序原理(拓扑、C3)
Python的多重继承问题-MRO和C3算法