面向对象(Python):学习笔记之继承
继承 面向对象的三大特性:
关于super
发布日期:2021-06-30 15:42:45
浏览次数:2
分类:技术文章
本文共 4865 字,大约阅读时间需要 16 分钟。
文章目录
-
封装:根据职责将属性和方法封装到一个抽象的类中
-
继承:继承实现代码的复用/重用,相同的代码不需要重复的编写
-
多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
1 单继承
1.1 单继承的概念 语法和特点
①. 单继承的概念
子类拥有父类的所有的方法和属性
②. 单继承的语法
class 子类名(父类名): pass
- 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
- 子类中应该根据职责,封装子类中特有的属性和方法
首先让看一下 使用继承 和 不使用继承 的区别.
如果不使用继承,开发一个动物类与狗类,则代码如下:class Animals: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡") class Dog: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡") def bark(self): print("汪汪汪")# 创建一个动物对象--狗对象wangcai_1 = Animals()wangcai_1.eat()wangcai_1.drink()wangcai_1.run()wangcai_1.sleep()wangcai_2 = Dog()wangcai_2.eat()wangcai_2.drink()wangcai_2.run()wangcai_2.sleep()wangcai_2.bark()
运行结果:
在这里可以看到,Animales类和Dog类有着四个函数是相同的,如果不使用继承,代码会非常冗余.如果再开发一个哮天犬类呢,毫无疑问代码会非常长且多余. 并且如果动物喝水的方法需要修改,我们则需要修改每一个类中的喝水方法,这显然太过于繁琐.如果使用继承:
class Animals: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡")class Dog(Animals): def bark(self): print("汪汪汪") wangcai = Dog()wangcai.eat()wangcai.drink()wangcai.run()wangcai.sleep()wangcai.bark()
运行结果:
很显然,Dog子类继承了Animales的所有属性和方法. 而使用继承后,代码显然间带了许多.③. 几个专业术语
- Dog类是Animal类的子类,Animal是Dog的父类,Dog类是Animal类继承
- Dog类是Animal类的派生类,Animal类是Dog的基类,Dog类是Animal类派生
④. 单继承的传递性
- C类从B类继承,B类又从A类继承
- 则C类具有B类和A类的所有属性和方法
即:子类拥有父类以及父类的父类中封装的所有属性和方法
class Animals: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡")class Dog(Animals): def bark(self): print("汪汪汪")class XiaoTianQuan(Dog): def fly(self): print("我飞了")xtq = XiaoTianQuan()xtq.eat()xtq.drink()xtq.run()xtq.sleep()xtq.bark()xtq.fly()
运行结果:
注意:子类只能继承自己的父类中的属性和方法,而不能继承和自己的父类从一个爷爷类中派生出来的类的方法. 即:XiaoTianQuan类不能继承Cat类中的方法1.2 方法的重写
- 子类拥有父类的所有属性和方法
- 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发.
方法的重写的应用场景:
- 当父类的方法实现不能满足子类的需求时,可以对方法进行重写(Override) 如果在子类中,对父类的方法进行了重写,则会执行子类中的方法而不执行父类中的方法. 如图:
重写父类方法的两种情况:
- 覆盖父类的方法 ①如果在开发中,父类的方法实现和子类的方法实现,完全不同 ②就可以使用覆盖的方式,在子类中重新编写父类的方法实现 具体的实现方式:就相当于在子类中定义了一个和父类同名的方法并实现 重写之后,在运行的时候,只会调用子类中重写的方法,而不会调用父类中封装的方法
- 对父类方法进行扩展 ①如果在开发中,子类的方法实现中包含父类的方法实现,即父类中原本封装的方法实现是子类方法的一部分. ②就可以使用扩展的方式 Ⅰ.在子类中重写父类的方法 Ⅱ.在需要的位置使用super().父类方法来调用父类方法的执行 Ⅲ.代码其他的位置针对子类的需求,编写子类特有的代码实现
关于super
- 在python中,super是一个特殊的类
- super()就是使用super类创建出来的对象
- 最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现
除此之外,调用父类名还有另外一种方式(Not important)
在Python 2.x的时候,如果需要调用父类的方法,可以使用以下方式- 父类名.方法(self)
- 不推荐使用,因为一旦父类发生变化,方法调用位置的类名同样需要进行修改.
提示:
- 在开发时,父类名 和 super()两种方式不要混用
- 如果使用当前子类名调用方法,会形成递归调用,出现死循环
class Animals: passclass Dog(Animals): def bark(self): print("汪汪汪")class XiaoTianQuan(Dog): def fly(self): print("我飞了") def bark(self): # 1.针对子类特有的需求,编写代码 print("我不想汪汪汪") # 2.保留父类的方法 super().bark() # 使用 父类名.方法(self) # Dog.bark(self) # 3.增加其他子类代码 print("123123")xtq = XiaoTianQuan()xtq.bark()
运行结果:
即: 如果向保留父类中的方法,首先要重写该方法,然后使用super().父类方法对其进行保留(调用),然后可以看情况增加后续代码.即实现了我们在原有父类方法上进行扩充的目的.1.3 父类的私有属性和私有方法
-
子类对象不能再自己的方法内部,直接访问父类的私有方法或者私有属性
-
子类对象可以通过父类的公有方法间接访问到私有属性或私有方法
①私有属性、方法 是 对象的隐私,不对外公开,外界以及子类都不能直接访问 ②私有属性、方法 通常用于做一些内部的事情 示例: -
B 的对象不能直接访问_num2属性
-
B 的对象不能在demo方法内访问_num2属性
-
B 的对象可以在demo方法内,调用父类的test方法
-
父类的test方法内部,能够访问_num2属性和_test方法
class A: def __init__(self): self.num1 = 100 self._num2 = 200 def _test(self): print("私有方法 %d %d" % (self.num1, self._num2)) def test(self): print("父类的公有方法") self._test() print("私有属性 %d" % self._num2)class B(A): def demo(self): print("%d" % self.num1) self.test()b = B();print(b)b.demo()
运行结果:
2 多继承
2.1 多继承的概念 语法和特点
① 多继承的概念
- 子类可以拥有多个父类,并且具有所有父类的属性和方法
- 例如:孩子会继承自己父亲和母亲的特征
②多继承的语法
class 子类名(父类名1,父类名2....): pass
class A: def test(self): print("test 方法")class B: def demo(self): print("demo 方法")class C(A, B): """多继承可以让子类对象 同时具有多个父类的属性和方法""" pass# 创建子类对象c = C()c.test()c.demo()
运行结果:
2.2 多继承的注意事项
Question:
如果不同的父类中存在同名的方法,子类对象在调用时候,会调用哪一个父类中的方法呢? 提示:开发时,应该尽量避免这种容易产生混淆的情况!如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承. 这种情况下,在底层代码设计中,会针对不同情况进行不同选择. 比如针对继承循序: 当然,不止有这一种选择方式.2.3 Python中的MRO-----方法搜索顺序
(仅供科普,不推荐使用重名多继承调用)
- python中针对类提供了一个内置属性__mro__可以查看方法搜索顺序
- MRO是 method resolution order,主要用于在多继承时判断方法,属性的调用
- 在搜索方法时,是按照__mro__的输出结果从左至右的顺序查找到
- 如果在当前类中找到方法,就继续执行,不在搜索
- 如果没有找到,就查找下一个类中是否有对应的方法,如果找到,就直接执行,不在搜索
- 如果找到最后一个类,还没有找到方法,程序报错
2.4 新式类与旧氏(经典)类
object是python中为所有对象提供的基类,提供一些内置的属性和方法,可以调用dir函数进行查看
- 新式类:以object为基类的类,推荐使用
- 经典类:不以object为基类的类,不推荐使用
- 在Python 3.x中,定义类时,如果没有指定父类,会默认使用object作为该类的基类–Python 3.x中定义的类都是新式类
- 在Python 2.x中,定义类时,如果没有指定父类,则不会使用object作为基类
新式类和经典类在使用多继承的时候,会影响到方法的搜索顺序
为了保证编写的代码能够同时在Python 2.x和Python 3.x中运行
在定义类的时候,如果没有父类,建议统一继承自 objectclass 类名(object): pass
转载地址:https://kaisarh.blog.csdn.net/article/details/103095736 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年05月04日 08时39分52秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
线程池excute方法执行底层过程
2019-05-01
线程池同步异步调用callable和Future
2019-05-01
梯度算法之初见
2019-05-01
解决python安装库较慢的方式
2019-05-01
Maven安装问题总结
2019-05-01
Maven 插件配置,安装配置问题
2019-05-01
PermGen space-永久区内存溢出
2019-05-01
Maven继承和聚合
2019-05-01
maven私服nexus配置
2019-05-01
nexus发布工程版本问题总结
2019-05-01
maven私服配置-发布工程版本到nexus
2019-05-01
Maven引入oracle驱动问题
2019-05-01
windows无法找到发送到桌面快捷方式
2019-05-01
redhat-vim文本编辑
2019-05-01
linux-文件挂载
2019-05-01
scala与java之间的集合类型转换
2019-05-01
Vue 3中令人激动的新功能:Fragment+Suspense+多v-model
2019-05-01
浅析Vuex及相关面试题答案
2019-05-01
Vue 3.0 中令人激动的新功能:Portals+新的自定义指令API
2019-05-01