继承:
1.继承
1.1继承
1 '''''' 2 """ 3 1.什么是继承? 4 继承是描述两个对象之间,什么是什么的关系 5 6 案例:麦兜,佩奇,猪刚鬓 -- 都是猪 7 8 在程序中,继承描述的是类和类之间的关系 9 10 例如:a 继承 b,a就能直接使用b已经存在的方法或属性 11 此时,a称之为子类,b被称之为父类,也称为基类 12 13 2.为什么要使用继承? 14 继承的一方制剂使用另一方已经有的东西 15 其目的是:提高重用性(重用已有的代码) 16 17 3.如何使用继承? 18 语法: 19 class 类名称(父类的名称): 20 21 ps:在Python中一个子类可以继承多个父类 22 查找继承顺序使用mro()列表 23 print(类名称.mro()) 24 """ 25 # 继承语法 26 class Person: # 父类 27 decs = '基类' 28 def say_hi(self): 29 print('fdj;kll;;jlkkl;') 30 class Teacher(Person): # 子类 31 pass 32 p = Teacher() 33 # 1.继承属性 34 print(p.decs) # 基类 35 # 2.继承方法 36 print(p.say_hi()) 37 # fdj;kll;;jlkkl; 38 # None 39 p.say_hi() # fdj;kll;;jlkkl;
1.2抽象
1 '''''' 2 """ 3 继承与抽象 4 抽象:不具体不清晰,看不懂,一种概念 5 继承的正确打开方式: 6 方式一: 7 先抽象(形成一个具有公共属性的类), 8 再继承(继承抽象形成的类). 9 方式二: 10 继承一个现存的类,新添加新的功能 11 """ 12 # 案例1 13 # 抽象 14 # 抽取老师和学生中相同的属性,形成的类 15 class Person: 16 def __init__(self,name,age,gender): 17 self.name = name 18 self.age = age 19 self.gender = gender 20 def say_hi(self): 21 print("name:%s,age:%s,gender:%s"%(self.name,self.age,self.gender)) 22 class Teacher(Person): 23 # def __init__(self,name,age,gender): 24 # self.name = name 25 # self.age = age 26 # self.gender = gender 27 # def say_hi(self): 28 # print("name:%s,age:%s,gender:%s"%(self.name,self.age,self.gender)) 29 pass 30 class Student(Person): 31 def __init__(self,name,age,gender,number): 32 super().__init__(name,age,gender) 33 self.number = number 34 def say_hi(self): 35 super().say_hi() 36 print("number:%s"%(self.number)) 37 38 s = Student('llx','28','198','10') 39 s.say_hi() 40 """ 41 name:llx,age:28,gender:198 42 number:10 43 """ 44 # 案例2 45 class Teacher1: 46 def __init__(self,name,age,gender): 47 self.name = name 48 self.age = age 49 self.gender = gender 50 def say_hi(self): 51 print("name:%s,age:%s,gender:%s"%(self.name,self.age,self.gender)) 52 class Student1(Teacher1): 53 def __init__(self,name,age,gender,number): 54 super().__init__(name,age,gender) 55 self.number = number 56 def say_hi(self): 57 super().say_hi() 58 print("number:%s"%(self.number)) 59 60 s = Student1('wyf','28','198','20') 61 s.say_hi() 62 ''' 63 name:wyf,age:28,gender:198 64 number:20 65 '''
1.3组合
1 '''''' 2 """ 3 组合:(把类作为属性,传给另一个类) 4 也是一种关系, 5 表示两个对象之间是什么有什么的关系 6 7 例如:学生有手机,游戏角色有装备 8 9 将一个对象作为另一个对象的属性, 10 即:什么有什么 11 12 组合的目的: 13 降低耦合度 14 为了重用现有代码 15 (关联起来,使用其中的方法) 16 17 18 """ 19 # 案例 20 class Phone: 21 def __init__(self,price,app,music): 22 self.price = price 23 self.app = app 24 self.music = music 25 def tall_phone(self): 26 print('price:%s,app:%s,music:%s'%(self.price,self.app,self.music)) 27 class Student: 28 # ps:把Phone类作为属性传给Student 29 def __init__(self,name,age,phone): 30 self.name = name 31 self.age = age 32 self.phone = phone 33 def study(self): 34 print('name%s:,age:%s,phone:%s'%(self.name,self.age,(self.phone.price,self.phone.app,self.phone.music))) 35 p = Phone('1998','qq音乐','风灯') 36 s = Student('llx','24',p) 37 print(s.phone.price) # 1998 38 s.phone.tall_phone() # price:1998,app:qq音乐,music:风灯 39 s.study() # namellx:,age:24,phone:('1998', 'qq音乐', '风灯')
ps:继承与组合对比
1 '''''' 2 """ 3 1.什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系 4 5 6 2.什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类 7 8 另外组合相比继承,耦合度更低了 9 """
1.4菱形继承--了解
1 '''''' 2 """ 3 菱形继承--了解 4 Python支持多继承 5 定义: 6 当一个了有多个父类,多个父类有共同基类,称为菱形继承 7 """ 8 class E: 9 a = 'm' 10 b = 'n' 11 c = 'o' 12 d = 'p' 13 e = 'e' 14 class B(E): 15 a = 'g' 16 b = 'b' 17 class C(E): 18 a = 'h' 19 b = 'i' 20 c = 'c' 21 class D(E): 22 a = 'j' 23 b = 'k' 24 c = 'l' 25 d = 'd' 26 27 class A(B,C,D): 28 a = 'a' 29 q = A() 30 # 先深度,进入父类,多个父类,按广度找,最后在按深度 31 print(q.e) # e 32 print(q.d) # d 33 print(q.c) # c 34 print(q.b) # b 35 print(q.a) # a 36 37 # 多继承查找顺序mro()列表 -- 先深度,遇到共同父类,在广度 38 # ps :当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度 39 # 新式类,就是深度优先 40 A.mro() 41 print(A.mro()) # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.E'>, <class 'object'>]
2.属性的内容
2.1属性的查找顺序
ps:mro()列表查找访问顺序
语法:print(类名称.mro())
1 '''''' 2 """ 3 1.属性的查找顺序 4 先找对象自己 --- > 自己的类 --- > 父类 --- > 父类的父类 --- > 基类(object) 5 2.方法 6 mro()列表,查询属性的查找顺序 7 """ 8 # 案例 9 class A: 10 text = '嘿嘿' 11 txt = '数据库' 12 py = '运行员' 13 xml = '前端' 14 class B(A): 15 text = '哈哈' 16 txt = '文件夹' 17 py = '运行' 18 class C(B): 19 text = '娃哈哈' 20 txt = '文件' 21 # 对象 22 p = C() 23 p.text = '嘻嘻嘻嘻' 24 # 1.先找对象自己 25 print(p.text) # 嘻嘻嘻嘻 26 # 2.再找自己类 27 print(p.txt) # 文件 28 # 3.再找父类 29 print(p.py) # 运行 30 # 4.自找父类的父类 31 print(p.xml) # 前端 32 # 5.自找基类 33 p.__init__() 34 print(p.__init__() ) # None 35 36 # 使用方法 37 print(C.mro()) # [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
2.2派生
1 '''''' 2 """ 3 派生: 4 属性在子类中存在 5 父类中完全没有的属性,称为派生 6 7 通常子类都会新增一些功能属性,不可能和父类完全一样,都可以称为派生, 8 即派生指的就是子类 9 """ 10 # 案例 11 class A: 12 text = '嘿嘿' 13 txt = '数据库' 14 py = '运行员' 15 xml = '前端' 16 def g(self): 17 print('哈哈') 18 class B(A): 19 text = '哈哈' 20 txt = '文件夹' 21 py = '运行' 22 def h(self): 23 print('heihei') 24 class C(B): 25 text = '娃哈哈' 26 txt = '文件' 27 css = 'jq' 28 def f(self): 29 print('嘿嘿') 30 # 对象 31 p = C() 32 # 1.类覆盖 33 p.text = '嘻嘻嘻嘻' 34 # 1.覆盖 35 print(p.text) # 嘻嘻嘻嘻 36 # 2.覆盖 37 print(p.txt) # 文件 38 # 3.覆盖 39 print(p.py) # 运行 40 # 类派生 41 # 1.派生 42 print(p.xml) # 前端 # 与基类做对比 43 # 2.派生 44 print(p.css) # jq 45 46 # 对象派生 47 p.f() # 嘿嘿 48 p.h() # heihei 49 p.g() # 哈哈
2.3覆盖
1 '''''' 2 """ 3 覆盖:也称之为重写overrides(覆盖) 4 当子类中出现与父类中完全一致的属性或方法, 5 由于属性的查找顺序, 6 所以父类的同名属性被覆盖 7 """ 8 class A: 9 text = '嘿嘿' 10 txt = '数据库' 11 py = '运行员' 12 xml = '前端' 13 def f(self): 14 print(111111) 15 class B(A): 16 text = '哈哈' 17 txt = '文件夹' 18 py = '运行' 19 def f(self): 20 print(2222) 21 class C(B): 22 text = '娃哈哈' 23 txt = '文件' 24 def f(self): 25 print(3333) 26 # 对象 27 p = C() 28 p.text = '嘻嘻嘻嘻' 29 # 类属性 30 # 1.覆盖 31 print(p.text) # 嘻嘻嘻嘻 32 # 2.覆盖 33 print(p.txt) # 文件 34 # 3.覆盖 35 print(p.py) # 运行 36 # 4.派生 37 print(p.xml) # 前端 38 39 # 对象属性 40 p.f() # 3333
3.子类访问父类的内容
3.1子类访问父类,三种方法
1 '''''' 2 """ 3 子类访问父类的方法:三种方法 4 1.方法一(python2) 5 语法: 6 super(当前类名称,self).名字(你要调的父类属性或方法) 7 2.方法二(python3) 8 语法: 9 super().名字(你要调的父类属性或方法) 10 3.方法三(直接指定类名称(你要调的父类属性或方法(self)),调用) 11 指名道姓调用 12 ps:指名道姓调用和继承无关 13 14 """
3.2自定义list--MyList
1 '''''' 2 # 案例 3 ''' 4 结论: 5 当你继承一个你现有的类, 6 并且覆盖了父类的__init__(初始化,创建对象的时候触发)方法时, 7 8 必须在初始化方法的'第一行'调用父类的初始化方法,并传入父类所需参数 9 ''' 10 ''' 11 继承内置list,定义我自己的mylist 12 ''' 13 class MyList(list): 14 def __init__(self,element_type): 15 # 调用父类的初始化方法,来完成基本的初始化 16 super().__init__() 17 self.element_type = element_type 18 def append(self, object): 19 """ 20 21 :param object: 是要存储的元素 22 :return:没有/None 23 """ 24 if type(object) == self.element_type: 25 # 我们需要在这里访问父类的append函数来完成真正的存储操作 26 super(MyList,self).append(object) 27 else: 28 print("sorry sir ,your element type not is %s"%self.element_type) 29 30 # 创建指定要存储的元素类型 31 # m = MyList(int) 32 # # 当你有需求时,需要在创建对象时,干点什么事,我就该想到初始化方法 33 # m.append(1) 34 # print(m[0]) # 1 35 # print(m.__dict__) 36 # print(m) # [1] 37 m1 = MyList(str) 38 m1.append('dgggdg') 39 print(m1) # ['dgggdg'] 40 m2 = MyList(dict) 41 m2.append({1:'d'}) 42 print(m2) # [{1: 'd'}]
3.3坑点 ___init__
1 '''''' 2 """ 3 坑点: 4 结论: 5 当你继承一个现有的类,并且你要覆盖父类__init__的方法,必须,先调用下父类的__init__,赋予初始值 6 7 """ 8 class Person: 9 def __init__(self,name,gender,age): 10 self.name = name 11 self.gender = gender 12 self.age = age 13 def say_hi(self): 14 print("name:%s,gender:%s,age:%s"%(self.name,self.gender,self.age)) 15 16 class Student(Person): 17 def __init__(self,name,gender,age,number): 18 super().__init__(name,gender,age) 19 self.number = number 20 def say_hi(self): 21 super().say_hi() 22 print("number:%s"%(self.number)) 23 s = Student('llx','98','24','10') 24 print(s.__dict__) # {'name': 'llx', 'gender': '98', 'age': '24', 'number': '10'} 25 s.say_hi() 26 # name:llx,gender:98,age:24 27 # number:10
4.新式类与经典类 -- 补充
4.1新式类
1 '''''' 2 """ 3 新式类:Python3中都是新式类 4 新式类:任何显式或隐式中继承自object,都是新式类 5 """
4.2经典类
1 '''''' 2 """ 3 经典类:即,不是object子类,仅在Python2中出现 4 """