Python 类抽象与继承 派生覆盖 组合 属性查找顺序 新式类菱形继承
class 父类名称: 类的内容 class 子类名称(父类名称): 类的内容 #在python中 一个子类可以同时继承多个父类
class Teacher: school = "oldboy" def __init__(self,name,age): self.name = name self.age = age def say_hi(self): print("hello i am %s" % self.name) def teach(self): print("正在教书......") class Student(Teacher): pass # 问题:学生类继承了老师类,所以学生类都具备了老师类的name,age属性和say_hi,teacher方法。但是teacher方法应该是老师独有的,学生不应该具备。 # 解决:抽象 class OldBoyPerson: school = "oldboy" def __init__(self,name,age): self.name = name self.age = age def say_hi(self): print("hello i am %s" % self.name) class Teacher(OldBoyPerson): def teach(self): print("正在教书......") class Student(OldBoyPerson): pass # 学生类和老师类继承了OldBoyPerson类,都具备name,age属性和say_hi,teacher方法。但是teacher方法应该是老师独有的,学生不具备。
3.继承的正确使用:先抽象再继承
class A: text = "haha" class B(A): text = "heihei" pass b = B() b.text = "xixi" print(b.text) # xixi" 对象自己的 - > 所在类中 -> 找父类 - >父类的父类 ->Object
class Person: name = 'person' def say_hi(self): print("hello") class Student(Person): name = 'student' # 覆盖 age= 18 # 派生 def say_hi(self): # 覆盖 print("hello world!") stu = Student() print(stu.name) # student print(stu.age) # 18 stu.say_hi() # hello world!
方式1: super(当前类名称,self).你要调的父类的属性或方法 方式2: super().你要调的父类的属性或方法,推荐使用 方式3: 类名称.你要调的父类的属性或方法(self) #方式3与继承无关 class Parent: text = "abc" def say_something(self): print("anything") class Sub(Parent): def show_info(self): # print(super(Sub,self).text) # super(Sub,self).say_something() # 访问方式2 py3的新语法 最常用的方式 print(super().text) super().say_something() #方式3 直接指定类名调用 # print(Parent.text) # Parent.say_something(self) sub = Sub() sub.show_info() # abc anything
class Person: text = "321" def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def sleep(self): print("人类 午睡 躺着睡!") def say_hi(self): print("my name :%s my age :%s my gender: %s " % (self.name,self.age,self.gender),end="") class Student(Person): text = "123" def __init__(self,name,age,gender,number): #======================================================================重点在这里 # 由于父类已经存在一个方法可以完成这个三参数的初始化 # 所以可以直接调用父类的初始化完成这部分的初始化工作 # 方法1 # Person.__init__(self,name,age,gender) # 指名道姓的调用 # 方法2 在py2中不支持 super().__init__(name,age,gender) # py2的写法 # super(Student, self).__init__(name,age,gender) self.number = number #====================================================================== # 访问父类的属性 def show_text(self): print(self.text) print(super().text) def say_hi(self): super().say_hi() print("my number: %s" % self.number) # print("my name :%s my age :%s my gender: %s my number: %s" % (self.name, self.age, self.gender,self.number)) s = Student("jack",20,"man","007") s.say_hi() # s.show_text()
class PC: def open_app(self,app_name): print("open %s" % app_name) class OldBoyStudent: def __init__(self,PC,notebook): self.PC = PC self.notebook = notebook pass pc = PC() notebook = PC() stu = OldBoyStudent(pc,notebook)
stu.notebook.open_app("pycharm")
组合的目的:
也是为了重用现有代码
什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系
什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类
另外组合相比继承,耦合度更低了
当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度
class A: # a = 1 pass class B(A): # a = 2 pass class C(A): # a = 3 pass class D(A): # a = 4 pass class E(B,C,D): # a = 5 pass e1 = E() # print(e1.a) # 新式类的顺序 # E B C D A object # 经典类的顺序 # E B A C D # print(E.mro()) 注意:经典类没有mro列表
""" 需求 实现一个能够限制元素类型的列表类 """ class MyList(list): def __init__(self,element_type): super().__init__() # 调用父类的初始化方法 来完成基本的初始化 self.element_type = element_type def append(self, object): """ :param object: 是要存储的元素 :return: 没有 """ if type(object) == self.element_type: #我们需要在这里访问父类的append函数来完成真正的存储操作 super(MyList,self).append(object) else: print("sorry sir, you element type not is %s" % self.element_type) # 创建是指定要存储的元素类型 m = MyList(int) # 当你有需求,是需要在创建对象时 干点什么事儿 那就该想到初始化方法 m.append(1) print(m[0]) m.append("121212")
class A: # a = 1 pass class B(A): # a = 2 pass class C(A): # a = 3 pass class D(A): # a = 4 pass class E(B,C,D): # a = 5 pass e1 = E() # print(e1.a) # 新式类的顺序 # E B C D A object # 经典类的顺序 # E B A C D print(E.mro()) # <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>] # 注意:经典类没有mro列表