《Python》 面向对象三大特性之继承
一、继承大纲:
继承和抽象(两个概念)
1、单继承:
语法:
父类、基类、超类
子类、派生类
继承与重用:子类可以使用父类中的名字(变量和方法)
继承与派生:子类在父类的基础上又新创建了自己需要的方法和属性
父类有的子类没有 - 子类对象直接调用,就会直接执行父类的方法
父类有的子类也有 - 子类对象调用,直接执行子类中的方法
想在子类中使用父类的方法:
父类名.方法名(self,...)
super().方法名(....)
规范的编程模式:抽象类
2、多继承:
语法:
接口:Python 和 c++ 没有接口,只有多继承,c# 和 Java 才有接口
新式类和经典类:(继承了object的类就是新式类)
新式类中:(Python 3.x都是新式类)
所有的多继承关系寻找方法的顺序--->遵循广度优先算法
继承object
mro方法 # 查看多继承关系查找顺序(print(类名.mro()))
super:super不是单纯的找父类,而是遵循mro顺序的
经典类:(Python2.7以前都是经典类,2.7以后经典类与新式类并存)
Python 2.x
不主动继承object
经典类在找父类中方法的过程中--->遵循深度优先
不提供mro方法和super
二、什么是继承:
继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
Python中类的继承分为:单继承和多继承:
class ParentClass1: # 定义父类
pass
class ParentClass2: # 定义父类
pass
class SubClass1(ParentClass1): # 单继承,基类(父类)是ParentClass1,派生类(子类)是SubClass
pass
class SubClass2(ParentClass1,ParentClass2): # Python支持多继承,用逗号分隔开多个继承的类
pass
查看继承:
>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
提示:如果没有指定基类,Python的类会默认继承object类,object是所有Python类的基类(老祖宗),它提供了一些常见方法(如__str__)的实现。
>>> ParentClass1.__bases__
(<class 'object'>,)
>>> ParentClass2.__bases__
(<class 'object'>,)
三、继承与抽象(先抽象再继承)
1、抽象即抽取类似或者说比较像的部分。
抽象分成两个层次:
1、将奥巴马和梅西这俩对象比较像的部分抽取成类;
2、将人,猪,狗这三个类比较像的部分抽取成父类。
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)

2、继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。

四、继承与重用性
在开发程序的过程中,如果我们定义了一个类A,然后又想新建立一个类B,但是类B的大部分内容与类A的相同时,我们不可能从头开始写一个类B,这就用到了类的继承的概念。
通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据类型和函数属性),实现代码重用
# 猫类 :
# 属性 : 名字,品种,食物
# 方法 : 叫,抓老鼠,吃,喝
# 狗类 :
# 属性 : 名字,品种,食物
# 方法 : 叫,看家,吃,喝
class Animal:
def __init__(self,name,kind,food,language):
self.name = name
self.kind = kind
self.food = food
self.language = language
def yell(self):
print('%s叫' % self.language)
def eat(self):
print('吃%s' % self.food)
def drink(self):
print('喝水')
class Cat(Animal):
def catch_mouse(self):
print('抓老鼠')
class Dog(Animal):
def look_after_house(self):
print('看家') # 继承
# 父类/超类/基类 :Animal
# 子类/派生类 :Cat、Dog # 继承与重用 - 父类中所有的属性和方法都可以被子类使用了
cat = Cat('阿猫','橘猫','牛杂','喵喵')
print(cat.name) #阿猫
cat.drink() #喝水
cat.eat() #吃牛杂
cat.yell() #喵喵叫 dog = Dog('阿狗','土狗','阿猫','汪汪')
print(dog.name) #阿狗
dog.drink() #喝水
dog.eat() #吃阿猫
dog.yell() #汪汪叫
继承与重用
提示:用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大生了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大。
五、派生
子类在父类的基础上又创建了自己的新的方法和属性
当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
# 派生
class Animal:
def __init__(self,name,kind,food,language):
print('in animal')
self.name = name
self.kind = kind
self.food = food
self.language = language
def yell(self):
print('%s叫' % self.language)
def eat(self):
print('吃%s' % self.food)
def drink(self):
print('喝水')
class Cat(Animal): # Animal的派生类
def __init__(self,name,kind,food,language,eye_color):
print('in Cat')
self.eye_color = eye_color # 派生属性
Animal.__init__(self,name,kind,food,language) # 需要手动添加self
# super().__init__(name,kind,food,language) # 不需要手动添加self
def catch_mouse(self): # 派生方法
print('抓老鼠')
def eat(self): # 不仅执行了父类中的基础功能,还完成了特殊的功能
Animal.eat(self)
# super().eat()
self.weight = 10
class Dog(Animal):
def look_after_house(self):
print('看家')
def eat(self):
# Animal.eat(self)
super().eat()
self.drink()
cat = Cat('阿猫','橘猫','牛杂','喵喵','绿色')
print(cat.eye_color) # 绿色
print(cat.food) # 牛杂
cat.catch_mouse() # 抓老鼠
cat.eat() # 吃牛杂
print(cat.weight) #
# 当子类当中有要被调用的方法的时候,子类的对象会直接选择子类中的方法、变量,父类中的方法不会被自动执行
# 如果我们既想要执行子类的方法,也想要执行父类的方法,那么需要在子类的方法中调用父类的方法:
# 父类名.方法名(self,...)
# super().方法名(...)
# 帮助我们在子类中调用父类中的同名方法
派生实例
六、抽象类与接口类
接口类:
# java c#
# 不允许多继承
# 接口 Interface 接口可以被多继承 # Interface FlyAnimal: # 规范继承我的类必须实现这个方法
# def fly():pass # Interface WalkAnimal:
# def walk():pass # Interface SwimAnimal:
# def swim():pass # class Tiger(WalkAnimal,SwimAnimal): 继承了一个规范
# def walk():代码
# def swim():代码
抽象类:只能被继承,不能被实例化(模板,规则)
# 工作中 公司有使用抽象类开发的规则
# 源码 别人使用抽象类 # 支付功能
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 模板的功能
@abstractmethod # abstractmethod是一个装饰器,装饰器怎么用?放在函数/类的上一行
def pay(self):pass @abstractmethod
def shouqian(self):pass class Alipay(Payment):
def pay(self,money):
print('使用支付宝支付了%s元'%money) class Wechatpay(Payment):
def pay(self,money):
print('使用微信支付了%s元'%money) class ApplePay(Payment):
def pay(self,money):
print('使用applepay支付了%s元' % money) def pay(obj,money):
obj.pay(money) p = Payment()
# a = Alipay()
# # a.pay(100)
# pay(a,100)
#
# we = Wechatpay()
# # we.pay(200)
# pay(we,200)
#
# ap = ApplePay() # 规范
# 多人开发、复杂的需求、后期的扩展
# 手段 来帮助我们完成规范 # 抽象类
# 抽象类是一个规范,它基本不会实现什么具体的功能,抽象类是不能被实例化
# 要想写一个抽象类
# from abc import ABCMeta,abstractmethod
# 在这个类创建的时候指定 metaclass = ABCMeta
# 在你希望子类实现的方法上加上一个 @abstractmethod装饰器
# 使用抽象类
# 继承这个类
# 必须实现这个类中被@abstractmethod装饰器装饰的方法
七、钻石继承

class A(object):
def test(self):
print('from A') class B(A):
def test(self):
print('from B') class C(A):
def test(self):
print('from C') class D(B):
def test(self):
print('from D') class E(C):
def test(self):
print('from E') class F(D,E):
# def test(self):
# print('from F')
pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A
#经典类继承顺序:F->D->B->A->E->C
#python3中统一都是新式类
#pyhon2中才分新式类与经典类 继承顺序
继承顺序
继承原理:
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如
>>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>,
<class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
八、继承小结:
继承的作用:
1、提高代码的重用性
2、提高代码的可读性
3、规范编程模式
几个名词:
1、抽象:抽象即抽取类似或者说比较像的部分,是一个从具体到抽象的过程
2、继承:子类继承了父类的方法和属性
3、派生:子类在父类方法和属性的基础上产生了新的方法和属性
抽象类与接口类:
1、多继承问题:
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
2、方法的实现:
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
钻石继承:
新式类:广度优先
经典类:深度优先
《Python》 面向对象三大特性之继承的更多相关文章
- python面向对象三大特性之继承
继承是创建新类的方法,以下是几个概念 父类,基类,超类: 被继承的类 子类,派生类:继承而产出的类 单继承:继承一个父类 多继承:继承多个父类 继承: 什么是什么的关系 父类中没有的属性,在字类中出现 ...
- python面向对象三大特性之一继承、多态、封装
继承,即在定义一个类时,以另一个类为参数,则称这个新定义的类继承了参数类,父类又称为基类. 单继承表示只继承一个类,多继承表示继承多个类. class parent1: pass class pare ...
- python 面向对象三大特性(封装 多态 继承)
今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面 ...
- python面向对象-三大特性
python面向对象编程三大特性 小结:前面我们说完了类和对象的关系,相信对类和对象的理解更加透彻..让我们一起去研究面向对象的三大特性吧.... 继承 1.什么继承? 在程序中继承就是事物之间的所属 ...
- python 面向对象(三大特性)
python 面向对象(初级) (思维导图 ↑↑↑↑↑) 概述: 面向过程:根据业务逻辑从上到下垒代码. 函数式:将某功能代码封装至函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类 ...
- python面向对象三大特性
面向对象的三大特性: 封装.继承和多态 一.封装 封装,顾名思义就是将内容封装到某个地方,以后可以直接调用被封装到某处的内容. - 将内容封装到某处 - 从某处调用被封装的内容 第一步,将内容封装到某 ...
- 面向对象编程(九)——面向对象三大特性之继承以及重写、Object类的介绍
面向对象三大特性 面向对象三大特征:继承 :封装/隐藏 :多态(为了适应需求的多种变化,使代码变得更加通用!) 封装:主要实现了隐藏细节,对用户提供访问接口,无需关心方法的具体实现. 继承:很好的实现 ...
- python学习 day23 面向对象三大特性之继承
### 面向对象三大特性值继承#### 1.什么是继承 继承是一种关系,必须存在两个对象才可能产生这种关系,在现实生活中的继承,王思聪可以继承王健林的财产 被继承的成为父,继承的一方成为子 在程序中, ...
- python基础(24):面向对象三大特性一(继承)
1. 继承 1.1 什么是继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类. python中类的继承分为:单继承和多继 ...
随机推荐
- Zookeeper一致性协议原理Zab
ZooKeeper为高可用的一致性协调框架,自然的ZooKeeper也有着一致性算法的实现,ZooKeeper使用的是ZAB协议作为数据一致性的算法, ZAB(ZooKeeper Atomic Bro ...
- zedgraph右键菜单的汉化
http://blog.csdn.net/jeryler/article/details/7876376 修改 zedGraphControl的ContextMenuBuilder事件即可! zedG ...
- 2017 ACM/ICPC 新疆赛区 I 题 A Possible Tree 带权并查集
传送门 题意:给定一棵带权树的形态, 但是并不知道每天条边的具体权重. 然后给m个信息, 信息格式为u v val, 表示在树上u 到 v 的路径上经过的边的权重的异或和为val, 问前面最多有多少个 ...
- springboot中配置主从redis
测试redis的主从配置 redis实例 文件夹名称如下 redis_master_s redis_slaver1_s redis_slaver2_s redis.conf文件 master的redi ...
- gulp报错插件gulp-notify 配置项
var notify = require("gulp-notify"); module.exports = function(){ var args = Array.prototy ...
- 【Coursera】History: Dawn of Electronic Computing学后小结
今天学习了Coursera上University of Michigan开的互联网的历史.技术和安全课程的FirstWeek内容. 先是吐槽下这个Coursera,认证非常麻烦,PC端需要摄像头拍照. ...
- NS3 实验脚本的编写步骤
第一步:配置主机,安装模块 (1)创建N个节点: NodeContainer nodes; nodes.Creat(N); 比如我目前接触到的PointToPoint,N就是2 (2)利用拓扑助手He ...
- linux中批量替换文本中字符串--转载
(一)通过vi编辑器来替换.vi/vim 中可以使用 :s 命令来替换字符串.:s/well/good/ 替换当前行第一个 well 为 good:s/well/good/g 替换当前行所有 well ...
- ubuntu16.04上安装Jenkins,获取登陆密码
sudo cat /usr/share/tomcat7/.jenkins/secrets/initialAdminPassword
- (转)netty、mina性能对比分析
转自: http://blog.csdn.net/mindfloating/article/details/8622930 流行 NIO Framework netty 和 mina 性能测评与分析 ...