今日类容
1.什么是继承
2.继承的基本语法
3.继承与抽象
4.属性的查找顺序
5.派生与覆盖
6.如何实现一个可以限制元素的类型的列表
7.子类访问父类的内容
8.组合
9.菱形继承
一 什么是继承
1.什么是继承:
继承是一种关系,描述俩个对象之间,什么是什么的关系,
列如麦兜,佩奇,都是猪, 在程序中,继承描述的是类和类之间的关系
列如a继承了b,a就能直接使用b已经存在的方法和属性,a称之为子类,b称之为父类,也称之为基类
2.什么时候用继承:
假如已经有几个类,而类与类之间有共同的变量属性和函数属性,那就可以把这几个变量属性和函数属性提取出来作为基类的属性。而特殊的变量属性和函数属性,则在本类中定义,这样只需要继承这个基类,就可以访问基类的变量属性和函数属性。可以提高代码的可扩展性。
二 继承的基本语法
class Base: desc = "这是一个基类" def show_info(self): print(self.desc) def make_money(self): print("一天赚一个亿...") #指定父类位Base class SubClass(Base): pass obj = SubClass() #即使类中什么都没有也可以使用父类中已有的内容 obj.make_money() print(obj.desc)
三 继承与抽象
1.什么是抽象:
不具体,不清晰,看不懂,不是确切存在的,
将多个子类中相同的部分,进行抽取,形成一个新的类,这个过程也称之为抽象的过程
2.如何正确的使用继承:
1.先抽象在继承
2.继承一个已经现存的类,扩展或是修改原始的功能
案例 :
继承的错误示范:
1 class Teacher: 2 school = ‘oldboy‘ 3 def __init__(self,name,age): 4 self.name = name 5 self.age = age 6 7 def say_hi(self): 8 print(‘hello i am %s‘%self.name) 9 10 def teach(self): 11 print(‘正在教书‘) 12 13 class Student(Teacher): 14 pass 15 16 print(Student.school) 17 print(Student.say_hi) 18 print(Teacher.say_hi) 19 20 stu = Student(‘zy‘,19) 21 stu.say_hi() 22 stu.teach() 23 ‘‘‘ 24 上述案例中打招呼的技能老师和学生都有,但是老师教书的技能,学生不应该继承过来,这是不合理的 25 ‘‘‘
继承的正确示范:
1 # 继承的改良版: 需要先抽象在继承 2 3 class OldBoyPerson: 4 school = ‘oldboy‘ 5 def __init__(self,name,age): 6 self.name = name 7 self.age = age 8 9 def say_hi(self): 10 print(‘hello i am %s ‘% self.name) 11 12 class Teacher(OldBoyPerson): 13 def teach(self): 14 print(‘正在教书‘) 15 16 class Student(OldBoyPerson): 17 pass 18 19 # t = Teacher(‘zy‘,19) 20 # t.say_hi() 21 # t.teach() 22 23 s = Student(‘sm‘,19) 24 s.say_hi() 25 ‘‘‘ 26 总结:先抽象 定义一个把老师类和学生类都放在定义的一个人类之中,在人类中设置一个人类都会的打招呼技能 27 然后老师和学生在继承那个他们都会的一个技能就可以了
四 属性的查找顺序
查找顺序:对象自己的 - > 所在类中 -> 找父类 - >父类的父类 ->Object
案例:
class A: name = ‘scot‘ class B(A): name = ‘rose‘ pass b = B() b.name = ‘jack‘ print(b.name) print(b.__str__()) # 查找顺序 # 对象自己 - > 所在的类 -> 所在类的父类 -> 父类的父类 -> object
五 派生与覆盖
1.什么是派生:
当一个子类中出现了与父类中不同的内容时,这个子类就称之为派生类
通常子类都会写一些新的代码,不可能和父类完全一样 , 既通常都是派生类,
所以派生类指的就是子类
2.什么是覆盖:
也称之为重写 overrides
当子类出现了与父类名称完全一致的属性或是方法
案例:派生
1 派生: 2 当一个类继承自另一个类,并且这个子类,并且这个子类拥有与父类不同的类容 3 ‘‘‘ 4 5 class A: 6 def show_info(self): 7 print(‘hello world‘) 8 9 class B(A): 10 pass
案例:覆盖
1 覆盖(重写) 2 子类中出现了与父类相同的属性或者方法,就会覆盖掉父类的方法和属性 3 ‘‘‘ 4 class A: 5 text = ‘123‘ 6 def sjow_info(self): 7 print(‘hello world‘) 8 9 10 class B(A): 11 text = ‘321‘ 12 def show_info(self): 13 print(‘hello nishishabi‘) 14 15 pass 16 17 b = B() 18 b.show_info() 19 print(b.text)
六 如何实现一个可以限制元素的类型的列表
1 ‘‘‘ 2 继承已有的类来扩展新功能: 3 4 实现一个存储类,在提供基本的存取功能之外,还要可以限制存储元素的类型 5 ‘‘‘ 6 7 class MyList(list): 8 def __init__(self,element_cls): 9 # 当你覆盖init方法时,不要忘记调用super().init 函数让父类完成原有的初始化操作 10 super().__init__() 11 self.element_cls = element_cls 12 13 14 def append(self, object): 15 if object.__class__ == self.element_cls: 16 super().append(object) 17 else: 18 print(‘你只能存储%s类型‘%self.element_cls.__name__)# 19 20 21 # 可以指定存储的类型 22 li = MyList(str) 23 li.append(20) 24 li.append(‘123‘) 25 print(li)
七 子类访问父类的内容
1.语法
方式1:
super(当前类名称,self).你要调的父类的属性或方法
方式2:
super().你要调的父类的属性或方法
方式3:
类名称.你要调的父类的属性或方法(self)
#方式3与继承无关
注意:
当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的
第一行调用父类的初始化方法,并传入父类所需的参数
案例:
1 class Person: 2 text = ‘321‘ 3 def __init__(self,name,age,gender): 4 self.name = name 5 self.age = age 6 self.gender = gender 7 8 def sleep(self): 9 print(‘人类已经睡着了,午睡,躺着睡‘) 10 11 12 def say_hi(self): 13 print(f‘my name is {self.name} my age is {self.age} my gender is {self.gender}‘,end=" ") 14 15 class Student(Person): 16 text = ‘123‘ 17 def __init__(self,name,age,gender,number): 18 # 因为父类已经存在了一个方法可以完成这三个参数的初始化, 19 # 所以就可以吧还缺的一个参数 补上就好了,其他的直接调用父类的进行初始化 20 # Person.__init__(self,name,age,gender)# 指名道姓的调用 21 22 # 方法二,py2 不支持 23 super().__init__(name,age,gender) 24 self.number = number 25 26 # py 中的写法 27 # super(Student, self).__init__(name,age,gender) 28 # self.number = number 29 30 # 访问父类的属性 31 def show_text(self): 32 print(self.text) 33 print(super().text) 34 35 def say_hi(self): 36 super().say_hi() 37 print(f‘my num is {self.number}‘) 38 39 stu = Student(‘zy‘,19,‘man‘,‘0001‘) 40 41 stu.say_hi() 42 43 stu.show_text()
八 什么是组合
1. 什么是组合:
指的是 一个类把另一个类的对象作为自己的属性 就称之为组合
无处不在
当你定义一个类 并且这个类拥有某种类型的属性时 就称之为组合
都是用用来重用代码的方式:
组合描述的是 什么拥有什么的关系 学生 有 书 学生有手机
基础描述的是 什么是什么的关系 麦兜是猪 猪猪侠也是猪
2.组合的目的:
也是为了重用现有代码
什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系
什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类
另外组合相比继承,耦合度更低了
案例:
1 class Phone: 2 def __init__(self,price,kind,color): 3 self.price = price 4 self.kind = kind 5 self.color = color 6 7 def call(self): 8 print("正在呼叫XXXX;") 9 10 def send_message(self): 11 print("正在发送短信....") 12 13 14 class Student: 15 def __init__(self,name,gender,phone): 16 self.name = name 17 self.gender = gender 18 self.phone = phone 19 20 def show_info(self): 21 print("name:%s gender:%s" % (self.name,self.gender)) 22 23 phone = Phone(1000,"apple","red") 24 25 stu1 = Student("rose","male",phone) 26 stu1.phone.call()
九 菱形继承
补充:多继承的时候,如果多个父类出现了同名的属性和函数,
需要用mro列表啦查看真正的继承关系,
总结:super在访问父类属性时,是按照mro列表一层层网上找
什么是菱形继承:
python3中任何类都是直接或间接继承了Object
新式类,任何显式或隐式地继承自object的类就称之为新式类, python3中全都是新式类
经典类,既不是Object的子类 ,仅在python2中出现
当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度
新式类,就是深度优先
案例:
1 class A: 2 def test(self): 3 print(‘from A‘) 4 super().test() 5 6 7 class B: 8 def test(self): 9 print(‘from B‘) 10 pass 11 12 13 class C(A,B): 14 pass 15 16 c = C() 17 c.test() 18 print(C.mro()) 19 20 21 class A: 22 a = 1 23 pass 24 25 class B(A): 26 a = 2 27 pass 28 29 class C(A): 30 a =3 31 pass 32 33 class D(A): 34 a = 4 35 pass 36 37 class E(B,C,D): 38 a = 5 39 pass 40 41 e = E() 42 print(e.a) 43 print( E.mro())
原文:https://www.cnblogs.com/zahngyu/p/11246863.html