面向对象三大特性(*****)1继承 1. 什么是继承 继承是一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类/基类/超类 继承与现实生活中的继承一个意思 (例如 小明继承小明他爹财产 房子) 一个东西b继承了另外一个东西a b就拥有a的内容 在代码中 一个类b继承了另外一个类a b这个类 就拥有了a中全部属性 继承有3个特色: 1. 子类能够遗传/重用父类的属性(解决类与类之间代码冗余的问题) 2. 在python中一个子类能够同时继承多个父类 3. 在继承的背景下,类分为两种:新式类,经典类 新式类:但凡继承object类的子类,以及该子类的子子孙孙都是新式类 在python3中一个类即使是没有显式地继承任何类,默认就继承object类, 即在python3中全部类都是新式类 经典类:没有继承object类的子类,以及该子类的子子孙孙都是经典类 强调:只有在python2中才有经典类 在python2中若是一个类没有显式地继承任何类,并不会自动继承object类 2. 为什么要用继承:减小类与类之间的代码冗余 使用场景: 例如: 你的项目中须要两种对象 老师和学生 分析发现 老师和学生有不少类似之处 都有 姓名 性别 年龄 将相同的部分属性 抽取到一个共同父类中person 3. 如何继承 :先抽象再继承(抽取比较像的部分继承属性) # 在python中继承的特色?单继承(用一个父类)&多继承(用多个父类) class Person: 共有的属性 name age gender def sleep(): print(你们都须要睡觉 睡觉的过程也相同) def attendClass(): print("听到上课铃声 要去教室") =================== x = 2 class Foo: x = 1 pass obj = Foo() obj.x = 3 print(obj.x)2 抽象类 什么是抽象类 ** 与java同样,python也有抽象类的概念可是一样须要借助模块实现, 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化 抽象类是一个介于类和接口直接的一个概念, 同时具有类和接口的部分特性,能够用来实现归一化设计 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass3. 属性查找(*****) 在没有出现菱形继承的状况下,属性的查找是按照从左往右的顺序一个分支一个分支的找下去 在单继承背景下,不管是新式类仍是经典类属性查找顺序都同样 先obj->类->父类->... 在出现菱形继承(一个子类继承的多个分支最终汇聚到一个非object类)的状况下, 在多继承背景下,若是一个子类继承了多个分支,可是多个分支最终汇聚到一个非object类(菱形继承问题) 面试常问问题***** (新式类 继承object类的才是新式类 广度优先) (经典类 若是你直接建立一个类在2.7中就是经典类 深度优先) 新式类:广度优先查找,按照从左往右的顺序一个分支一个分支的找下去,在最后一个分支才去查找顶级类 obj->A->B->E->C->F->D->G->object 经典类(没有object类):深度优先查找,按照从左往右的顺序一个分支一个分支的找下去,在第一个分支就查找顶级类 obj->A->B->E->G->C->F->D (.mro()参考该对象所属类的mro查找) 类有两种属性:数据属性和函数属性 1. 类的数据属性是全部对象共享的 2. 类的函数属性是绑定给对象用的 在obj.name会先从obj本身的名称空间里找name, 找不到则去类中找,类也找不到就找父类... 最后都找不到就抛出异常4. 派生(*****) 在子类中定义本身的属性,若是与父类的属性重名,那以本身的为准. 在子类派生的新方法中重用父类的功能: 方式一:指名道姓地调用某一个类的函数 特色:类名.函数名(对象,参数1,参数2,...)==> 1. 与继承无关 2. 没有自动传值的效果 class OldboyPerson:#父类 school="oldboy" def __init__(self,name,age,gender): self.name=name self.age=age self.gender=gender class Teacher(OldboyPerson):#子类 def __init__(self,name,age,gender,level,salary): OldboyPerson.__init__(self,name,age,gender) # super(Teacher, self).__init__(name, age, gender) self.level = level self.salary = salary 方式二:super()获得一个特殊的对象,该对象专门用来引用父类的属性 特色:super(本身的类名, self).父类的方法(参数1,参数2,...) == > super().父类的方法(参数1,参数2,...) 1. 严格依赖继承,super会彻底参照类的mro列表去便历父类中属性依次查找 2. 有自动传值的效果 固然子类也能够添加本身新的属性或者在本身这里从新定义这些属性 (不会影响到父类),须要注意的是,一旦从新定义了本身的属性且与父类重名, 那么调用新增的属性时,就以本身为准了。 class Riven(Hero): camp='Noxus' def attack(self,enemy): #在本身这里定义新的attack,再也不使用父类的attack,且不会影响父类 print('from riven') def fly(self): #在本身这里定义新的 print('%s is flying' %self.nickname) 在子类中,新建的重名的函数属性,在编辑函数内功能的时候, 有可能须要重用父类中重名的那个函数功能,应该是用调用普通函数的方式, 即:类名.func(),此时就与调用普通函数无异了, 所以即使是self参数也要为其传值 class Riven(Hero): camp='Noxus' def __init__(self,nickname,aggressivity,life_value,skin): Hero.__init__(self,nickname,aggressivity,life_value) #调用父类功能 self.skin=skin #新属性 def attack(self,enemy): #在本身这里定义新的attack,再也不使用父类的attack,且不会影响父类 Hero.attack(self,enemy) #调用功能 print('from riven') def fly(self): #在本身这里定义新的 print('%s is flying' %self.nickname) r1=Riven('锐雯雯',57,200,'比基尼') r1.fly() print(r1.skin) ''' 运行结果 锐雯雯 is flying 比基尼 '''