继承与派生
在你即将学习“继承”这种东西的时候 你只要记住一条:
大部分使用继承的场合都可以用组合取代或简化,而多重继承则需要不惜一切的避免。
什么是继承?
1.在程序中继承是一种新建子类的方式,新创建的类称为子类\派生类,被继承的类称为父类\基类\超类
继承描述的是一种遗传关系,子类可以重用父类的属性
2.类的继承和派生其实是一回事,子类继承了父类,父类派生了子类。继承是从子类的角度来讲的,派生是从父类的角度来讲的。
(继承就是用来指明一个类的大部分或全部功能都是从一个父类中获得的。
例如:
写class Foo(Bar)时,就发生了继承效果,这行代码的意思是“创建一个叫Foo的类,并让它继承自Bar”。 当你写时 python 会让Bar的实例所具有的动作都工作在Foo的实例上。这样可以让你把通用的功能放到Bar里边,然后再给Foo特别设定一些功能。)
为何用继承?
减少类与类之间代码冗余的问题
如何使用: (先抽象再继承)
在python中 继承分为单继承&多继承
单继承如: Class Pide(Bre):
创建一个叫 Pide 的类,让它继承Bre这个类。
多继承如: Class Haha(Dawang,Xiaodi...):
创建一个叫 Haha 的类,让它继承 Dawang 和 Xiaodi两个类及更多个类。
python2与python3在继承上的区别:
新式类:但凡继承object类的子类,以及该 子类 的 子子类,都称之为新式类。
经典类:没有继承object类的子类,以及该 子类 的 子子类,都称之 经典类。
ps: 只有python2 中才区分新式类与经典类。
父类与子类有 3 种交互方式:
1.子类上的动作完全等同于父类上的动作。
2.子类上的动作完全覆盖了父类上的代码。
3.子类上的动作部分替换父类上的动作。
方式一 实例:(隐式继承)
class Parent(object): def implicit(self): print('PARENT impliclit()') class Child (Parent): pass dad = Parent( ) son = Child( ) dad.implicit( ) son.implicit( )
结果:
PARENT impliclit()
PARENT impliclit()
方式 二 实例:(显式继承)
# 实例: class Parent(object): def override(self): print('PARENT override()') class Child (Parent): def override(self): # ———— print("CHILD override") dad = Parent( ) son = Child( ) dad.override( ) son.override( ) #———#————#
如你所见,运行到(#——)时,这里运行的是Parent.override函数,因为dad这个变量是定义在Parent里的。不过运行到第(#——#——#)行,打印出来的却是Child.override里的消息,因为son 是Child的一个实例,而子类中新定义的函数在这里取代了父类里的函数。
结果:
PARENT override()
CHILD override
方式三 实例:(运行前或运行后替换)
# 实例: class Parent(object): def altered(self): print('PARENT altered()') class Child (Parent): def altered(self): print("CHILD this is one") #__6 super(Child,self).altered() #__7 print('CHILD this is twe') #__8 dad = Parent( ) son = Child( ) dad.altered( ) son.altered( )
如你所见: 1、由于我覆盖了Parent.altered,实际运行的是Child.altered,所以第6行执行结果是预料之中的。
2、这里我在前面和后面加一个动作,所以第6行之后我用super 来获取Parent.altered 这个版本。
3、第7行调用了super(Child,self).altered(),它还知道你的继承关系,并会访问到Parent类, 这句你可以读作“用Child 和 self 这两个参数调用 super,
然后在此返回的基础上调用altered。”
4、到这里函数Parent.altered版本就会运行,而且打印出了Parent里的消息。
5、最后,从Parent.altered返回,Child.altered 函数接着打印出后面的消息。
结果:
PARENT altered() CHILD this is one PARENT altered() CHILD this is twe
super 方法:
# super(OldboyTeacher,self),在python3中super可以不传参数,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中属性, # 强调:super会严格参照类的mro列表依次查找属性
super ()最常见的用法实在基类的__init__函数中使用。
ps: 通常这也是唯一可以进行这种操作的地方。
如:
class Parent(object): def xxx(self): print('this is xxx') class Child(Parent): def __init__(self,stuff): #在这里设一些变量 self.stuff = stuff super(Child,self).__init__() #然后才让Parent 用__init__完成初始化。
上面是一个在Child中完成上述行为的例子, 在这里你需要在子类里做了一些事情,然后在父类中完成初始化。
例子:
class OldboyPeople: school = 'Oldboy' def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class OldboyTeacher(OldboyPeople): def __init__(self, name, age, gender,level,salary): super(OldboyTeacher,self).__init__(name, age, gender) #看这里 结合上述 self.level=level self.salary=salary def score(self,stu,num): stu.num=num print('老师%s给学生%s打分%s' %(self.name,stu.name,num)) tea=OldboyTeacher('egon',18,'male',10,3000) #__init___(tea,'egon',18,'male',10,3000) print(tea.__dict__)
结果:
{'name': 'egon', 'age': 18, 'gender': 'male', 'level': 10, 'salary': 3000}
如何在子类派生出的新方法中重用父类的功能
1. 指名道姓地引用某一个类函数:类名.函数名()==>与继承无关
2. super(自己的类名,self).父类中的方法()==>严格以来继承,会按照触发属性查找的那个类的mro去遍历父类中属性