python面向对象的继承-组合-02

*面向对象(OOP)的三大特征:**# 封装、继承、多态

继承 什么是继承

继承:# 是一种关系,描述两个对象之间什么是什么的什么的关系

例如:麦兜、佩奇、猪猪侠、猪刚鬣,都是猪

为什么要使用继承

继承的好处:# 继承的一方可以直接使用被继承一方已经有的东西

程序中,继承描述的是类和类之间的关系

​ 例如:a继承了b,a就能直接使用b已经存在的方法和属性

​ 此时,a称之为子类,b称之为父类,也称之为基类。

为什么使用继承:# 其目的是为了重用已经有了的代码,提高重用性

如何使用继承 语法 class 类名称(父类的名称): # 在python中 一个子类可以同时继承多个父类

继承小案例(子类直接用父类的方法,无需自己实现)

class Base: desc = "这是一个基类" def show_info(self): print(self.des) @staticmethod def make_money(): print("一天赚ta一个亿") class SubClass: @staticmethod def make_money(): print("一天赚ta一百") pass class SubClass2(Base): # 通过继承使用父类的 make_money pass # 无继承 obj1 = SubClass() obj1.make_money() # 一天赚ta一百 # 继承,可得到父类的方法及属性 obj2 = SubClass2() obj2.make_money() # 一天赚ta一个亿 print(obj2.desc) # 这是一个基类

管理学生与老师小案例(老师类默认有教书的方法,而学生类是不可以有的,所以不能直接让学生类继承老师类)

# 需求:管理老师 class Teacher: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender def say_hi(self): print(f"name:{self.name},gender:{self.gender},age:{self.age}") t1 = Teacher('jack', 'male', 20) t1.say_hi() # name:jack,gender:20,age:male # 扩展需求:把老师也一起管理 class Student: def __init__(self, name, age, gender, number): self.name = name self.age = age self.gender = gender self.number = number def say_hi(self): print(f"name:{self.name},gender:{self.gender},age:{self.age}") s1 = Student('sushan', 'female', 18, 'xxx01') s1.say_hi() # name:sushan,gender:18,age:female

上面代码有些重复,学生和老师有很多属性都是一样的。

抽象

直意:不具体、不清晰、很模糊、看不太懂

编程中:# 将多个子类的中相同的部分,进行抽取,形成一个新的类,这个过程也称之为抽象

# 抽取老师学生的共同特征,然后再继承 class Person: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender def say_hi(self): print(f"name:{self.name},gender:{self.gender},age:{self.age}") pass class Teacher(Person): def teaching(self): print("老师教学生,写代码....") class Student(Person): pass t1 = Teacher('jack', 'male', 20) t1.say_hi() # name:jack,gender:20,age:male t1.teaching() # 老师教学生,写代码.... s1 = Student('rose', 'female', 20) s1.say_hi() # name:rose,gender:20,age:female # s1.teaching() # 报错,找不到teaching(他没有,他的父类也没有) 如何正确使用继承:

1.先抽象(提取特征)再继承

2.继承一个已经现存的类,扩展或是修改原始的功能

class A: text = 'haha' class B(A): text = 'heihei' # 注释掉访问父级的 pass b = B() print(b.text) # b自身没有,找类,就不用访问类的父类的了 # heihei b.text = 'xixix' print(b.text) # b(对象)自身有,就不能找类了 # xixix 属性的查找顺序

查找顺序:对象自身 --> 类 --> 父类 --> ...父类的上级父类... --> Object --> 报错

派生与覆盖(重写)

派生:# 当一个子类中出现了与父类中不同的内容时,这个子类就称之为派生类

class Person: @staticmethod def say_hi(): print("hello") # 这个Student子类不是派生,父类Person一模一样。(这样没啥意思) class Student(Person): pass

通常子类都会写一些新的代码,不可能和父类完全一样,即通常子类都是派生类

派生类就是子类的意思

覆盖:# 也称之为重写(overrides)当子类出现了与父类名称完全一样的属性或是方法,就是覆盖

class Person: @staticmethod def say_hi(): print("hello") # 这个Student子类不是派生,父类Person一模一样。(这样没啥意思) class Student(Person): @staticmethod def say_hi(): # 与父类的say_hi 重复,重写、覆盖 print("hello world!") pass s = Student() s.say_hi() # hello world!

练习:实现一个可以限制元素类型的容器(子类访问父类中的内容)

补充知识点

​ 子类访问父类的方法:# super(当前类名称, self).你要调用的父类的属性或方法

# 小练习:做一个可以限制元素类型的容器类型 class MyList(list): # 继承list,可以直接用list的一些方法属性 def __init__(self, data_type): super(MyList, self).__init__() # 应规范,子类重写父类方法的时候__init__初始化函数中要调用父类的__init__初始化函数 self.data_type = data_type def append(self, obj): ''' 重写父类的append方法 :param obj: 是要存储的元素 :return: None ''' if isinstance(obj, self.data_type): # if type(obj) == self.data_type: # 写法二 super(MyList, self).append(obj) # 这里需要访问父类的append 方法来完成真正的存储操作 else: print(f"非指定类型{self.data_type}!") # 创建时指定要存储的元素类型 str_list = MyList(str) str_list.append('abc') print(str_list[0]) # abc str_list.append(1) # 非指定类型<class 'str'>! 访问父类属性的三种方式 # 1.super(类, 对象自身).类的属性/方法 python2的写法(兼容写法,python2、3都可以用) # 2.super().类的属性/方法 python3的新语法 ***** (推荐,python2项目慎用哦) # 3.类.属性/方法 没啥实际意义,不是继承,这是直接用类来调用了

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyjdw.html