Python面向对象编程之继承与多态详解


Posted in Python onJanuary 16, 2018

本文实例讲述了Python面向对象编程之继承与多态。分享给大家供大家参考,具体如下:

Python 类的继承

在OOP(Object Oriented Programming)程序设计中,当我们定义一个class的时候,可以从某个现有的class 继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

我们先来定义一个class Person,表示人,定义属性变量 name 及 sex (姓名和性别);

定义一个方法print_title():当sex是male时,print man;当sex 是female时,print woman。参考如下代码:

class Person(object):
  def __init__(self,name,sex):
    self.name = name
    self.sex = sex
  def print_title(self):
    if self.sex == "male":
      print("man")
    elif self.sex == "female":
      print("woman")
class Child(Person):              # Child 继承 Person
  pass
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex)  # 子类继承父类方法及属性
May.print_title()
Peter.print_title()

而我们编写 Child 类,完全可以继承 Person 类(Child 就是 Person);使用 class subclass_name(baseclass_name) 来表示继承;

继承有什么好处?最大的好处是子类获得了父类的全部属性及功能。如下 Child 类就可以直接使用父类的 print_title() 方法

实例化Child的时候,子类继承了父类的构造函数,就需要提供父类Person要求的两个属性变量 name 及 sex:

在继承关系中,如果一个实例的数据类型是某个子类,那它也可以被看做是父类(May 既是 Child 又是 Person)。但是,反过来就不行(Peter 仅是 Person,而不是Child)。

继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。比如如下的继承树:

Python面向对象编程之继承与多态详解

isinstance()   及  issubclass()

Python 与其他语言不同点在于,当我们定义一个 class 的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样。

Python 有两个判断继承的函数:isinstance() 用于检查实例类型;issubclass() 用于检查类继承。参见下方示例:

class Person(object):
  pass
class Child(Person):         # Child 继承 Person
  pass
May = Child()
Peter = Person()
print(isinstance(May,Child))     # True
print(isinstance(May,Person))    # True
print(isinstance(Peter,Child))    # False
print(isinstance(Peter,Person))   # True
print(issubclass(Child,Person))   # True

Python 类的多态

在说明多态是什么之前,我们在 Child 类中重写 print_title() 方法:若为male,print boy;若为female,print girl

class Person(object):
  def __init__(self,name,sex):
    self.name = name
    self.sex = sex
  def print_title(self):
    if self.sex == "male":
      print("man")
    elif self.sex == "female":
      print("woman")
class Child(Person):        # Child 继承 Person
  def print_title(self):
    if self.sex == "male":
      print("boy")
    elif self.sex == "female":
      print("girl")
May = Child("May","female")
Peter = Person("Peter","male")
print(May.name,May.sex,Peter.name,Peter.sex)
May.print_title()
Peter.print_title()

当子类和父类都存在相同的 print_title()方法时,子类的 print_title() 覆盖了父类的 print_title(),在代码运行时,会调用子类的 print_title()

这样,我们就获得了继承的另一个好处:多态。

多态的好处就是,当我们需要传入更多的子类,例如新增 Teenagers、Grownups 等时,我们只需要继承 Person 类型就可以了,而print_title()方法既可以直不重写(即使用Person的),也可以重写一个特有的。这就是多态的意思。调用方只管调用,不管细节,而当我们新增一种Person的子类时,只要确保新方法编写正确,而不用管原来的代码。这就是著名的“开闭”原则:

对扩展开放(Open for extension):允许子类重写方法函数

对修改封闭(Closed for modification):不重写,直接继承父类方法函数

子类重写构造函数

子类可以没有构造函数,表示同父类构造一致;子类也可重写构造函数;现在,我们需要在子类 Child 中新增两个属性变量:mother 和 father,我们可以构造如下(建议子类调用父类的构造方法,参见后续代码):

class Person(object):
  def __init__(self,name,sex):
  self.name = name
  self.sex = sex
class Child(Person):        # Child 继承 Person
  def __init__(self,name,sex,mother,father):
    self.name = name
    self.sex = sex
    self.mother = mother
    self.father = father
May = Child("May","female","April","June")
print(May.name,May.sex,May.mother,May.father)

若父类构造函数包含很多属性,子类仅需新增1、2个,会有不少冗余的代码,这边,子类可对父类的构造方法进行调用,参考如下:

class Person(object):
  def __init__(self,name,sex):
    self.name = name
    self.sex = sex
class Child(Person):             # Child 继承 Person
  def __init__(self,name,sex,mother,father):
    Person.__init__(self,name,sex)    # 子类对父类的构造方法的调用
    self.mother = mother
    self.father = father
May = Child("May","female","April","June")
print(May.name,May.sex,May.mother,May.father)

多重继承

多重继承的概念应该比较好理解,比如现在需要新建一个类 baby 继承 Child , 可继承父类及父类上层类的属性及方法,优先使用层类近的方法,代码参考如下:

class Person(object):
  def __init__(self,name,sex):
    self.name = name
    self.sex = sex
  def print_title(self):
    if self.sex == "male":
      print("man")
    elif self.sex == "female":
      print("woman")
class Child(Person):
  pass
class Baby(Child):
  pass
May = Baby("May","female")    # 继承上上层父类的属性
print(May.name,May.sex)
May.print_title()         # 可使用上上层父类的方法
class Child(Person):
  def print_title(self):
    if self.sex == "male":
      print("boy")
    elif self.sex == "female":
      print("girl")
class Baby(Child):
  pass
May = Baby("May","female")
May.print_title()        # 优先使用上层类的方法

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
用Pygal绘制直方图代码示例
Dec 07 Python
Python subprocess模块详细解读
Jan 29 Python
TensorFlow如何实现反向传播
Feb 06 Python
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
Dec 14 Python
Python threading的使用方法解析
Aug 28 Python
python如果快速判断数字奇数偶数
Nov 13 Python
Python OrderedDict字典排序方法详解
May 21 Python
Python3爬虫中识别图形验证码的实例讲解
Jul 30 Python
Python脚本打包成可执行文件过程解析
Oct 20 Python
Django权限控制的使用
Jan 07 Python
如何用tempfile库创建python进程中的临时文件
Jan 28 Python
pytorch 预训练模型读取修改相关参数的填坑问题
Jun 05 Python
Python基于socket实现简单的即时通讯功能示例
Jan 16 #Python
python中将字典形式的数据循环插入Excel
Jan 16 #Python
python+tkinter编写电脑桌面放大镜程序实例代码
Jan 16 #Python
详解python函数传参是传值还是传引用
Jan 16 #Python
Python+tkinter使用80行代码实现一个计算器实例
Jan 16 #Python
Python使用matplotlib填充图形指定区域代码示例
Jan 16 #Python
python+matplotlib实现礼盒柱状图实例代码
Jan 16 #Python
You might like
模仿OSO的论坛(二)
2006/10/09 PHP
PHP中计算字符串相似度的函数代码
2012/12/29 PHP
php字符编码转换之gb2312转为utf8
2013/10/28 PHP
php安全配置记录和常见错误梳理(总结)
2017/03/28 PHP
PHP实现阿里大鱼短信验证的实例代码
2017/07/10 PHP
PHP后期静态绑定之self::限制实例分析
2018/12/21 PHP
PHP getID3类的使用方法学习笔记【附getID3源码下载】
2019/10/18 PHP
window.location和document.location的区别分析
2008/12/23 Javascript
JS打印gridview实现原理及代码
2013/02/05 Javascript
捕获浏览器关闭、刷新事件不同情况下的处理方法
2013/06/02 Javascript
js中apply方法的使用详细解析
2013/11/04 Javascript
jquery实现的鼠标拖动排序Li或Table
2014/05/04 Javascript
轻松创建nodejs服务器(10):处理上传图片
2014/12/18 NodeJs
深入浅出分析javaScript中this用法
2015/05/09 Javascript
基于jquery实现图片相关操作(重绘、获取尺寸、调整大小、缩放)
2015/12/25 Javascript
JavaScript程序中的流程控制语句用法总结
2016/05/23 Javascript
JavaScript鼠标事件,点击鼠标右键,弹出div的简单实例
2016/08/03 Javascript
Vue.js开发环境搭建
2016/11/10 Javascript
jQ处理xml文件和xml字符串的方法(详解)
2016/11/22 Javascript
利用JS实现简单的瀑布流加载图片效果
2017/04/22 Javascript
Vue.js移动端左滑删除组件的实现代码
2017/09/08 Javascript
vue移动端实现下拉刷新
2018/04/22 Javascript
使用JavaScript生成罗马字符的实例代码
2018/06/08 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
vuex存储token示例
2019/11/11 Javascript
vue实现防抖的实例代码
2021/01/11 Vue.js
JavaScript 中的执行上下文和执行栈实例讲解
2021/02/25 Javascript
Centos 升级到python3后pip 无法使用的解决方法
2018/06/12 Python
Django中密码的加密、验密、解密操作
2019/12/19 Python
浅析python表达式4+0.5值的数据类型
2020/02/26 Python
python raise的基本使用
2020/09/10 Python
任意一块网页内容实现“活”的背景(目前火狐浏览器专有)
2014/05/07 HTML / CSS
关于HTML5的安全问题开发人员需要牢记的
2012/06/21 HTML / CSS
HTML里显示pdf、word、xls、ppt的方法示例
2020/04/14 HTML / CSS
澳大利亚最大的百货公司:Myer
2018/12/21 全球购物
采购经理岗位职责
2014/02/16 职场文书