自学Python之路-Python基础+模块+面向对象
自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django

自学Python5.5-面向对象三大基本特征_继承

一、初始继承(单继承)

1.1  继承概念

继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

  • 通过继承创建的新类称为“子类”或“派生类”。
  • 被继承的类称为“基类”、“父类”或“超类”。
  • 继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
  • 一个子类可以被多个类继承。
  • 一个子类可以继承多个父类(只有在python里面才有)。
class A(object):pass   # 父类,基类,超类
class B:pass # 父类,基类,超类
class A_son(A,B):pass # 子类,派生类
class AB_son(A):pass # 子类,派生类

没有继承父类,默认继承object 。

1.2  继承与抽象(先抽象后继承)

抽象即抽取类似或者说比较像的部分。
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)。

继承:是基于抽象的结果,通过编程语言去实现它,肯定先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。

# 比如举例人狗大战。 以下有两个类,你会发现两个类有共同点
class Dog:
def __init__(self,name,aggr,hp):
self.name = name
self.aggr = aggr
self.hp = hp
def bitc(self,person):
person.hp -= self.aggr
class person:
def __init__(self,name,aggr,hp,sex):
self.name = name
self.aggr = aggr
self.hp = hp
self.sex = sex
self.money = 0
def attack(self,dog):
person.hp -= self.aggr
def get_weapon(self,weapon):
if self.money >= weapon.price:
self.money -= weapon.price
self.get_weapon = weapon
self.aggr += weapon.aggr
else:
print("余额不足,请先充值")  

将以上两个类相同的地方创建一个新的类, 两个类在继承新的类。

class Animal:
def __init__(self,name,aggr,hp):
self.name = name #人和狗都有自己的昵称
self.aggr = aggr #人和狗都有自己的攻击力
self.hp = hp #人和狗都有自己的生命值
class Dog(Animal):
def bitc(self,person):
person.hp -= self.aggr
class person(Animal):
pass
Liu = Dog("刘老板",200,500)
print(Liu.name)

举个例子:

一个狗类: 吃、喝、看门

一个鸟类: 吃、喝、下单

class Animal:
def __init__(self):
print('执行Animal.__init__')
self.func()
def eat(self):
print('%s eating'%self.name)
def drink(self):
print('%s drinking'%self.name)
def func(self):
print('Animal.func')
class Dog(Animal):
def guard(self):
print('guarding')
def func(self):
print('Dog.func')
class Bird(Animal):
def __init__(self,name):
self.name = name
def lay(self):
print('laying')  

比如定义一个实例 dog = Dog(),其中产生了一个问题

当执行Dog类的时候,Dog类没有__init__(self)就执行父类Animal的__init__(self),然后执行了self.func(),此时Animal和Dog类同时拥有self.func(),那么它执行哪个类的self.func()? 答案是:Dog的self.func()

提示:

用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大生了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大。

1.3  派生

当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

# 比如接上面的举例。
class Animal:
def __init__(self,name,aggr,hp):
self.name = name
self.aggr = aggr
self.hp = hp
class Dog(Animal):
def __init__(self,name,aggr,hp,kind):
self.kind = kind
def bitc(self,person):
person.hp -= self.aggr
Liu = Dog("刘老板",20,500,"吉娃娃")
print(Liu.name) # 报错,因为只执行Dog类里面的_init_,但是里面没有name 

class Animal:
def __init__(self,name,aggr,hp):
self.name = name
self.aggr = aggr
self.hp = hp
def eat(self):
print('吃药回血')
self.hp+=100
class Dog(Animal):
def __init__(self,name,aggr,hp,kind):
Animal.__init__(self,name,aggr,hp) #
self.kind = kind # 派生属性(父类没有的,子类新增的属性)
class Person(Animal):
def __init__(self,name,aggr,hp,sex):
Animal.__init__(self,name,aggr,hp)
self.sex = sex # 派生属性
self.money = 0 # 派生属性
Liu = Dog('刘老板',20,500,'吉娃娃')
Liu.eat() #使用的继承父类animal的eat方法
print(Liu.hp)
tong = Person('tong',1,2,None)
tong.eat() #使用的继承父类animal的eat方法
print(tong.hp)

class Animal:
def __init__(self,name,aggr,hp):
self.name = name
self.aggr = aggr
self.hp = hp
def eat(self):
print('吃药回血')
self.hp+=100
class Dog(Animal):
def __init__(self,name,aggr,hp,kind):
Animal.__init__(self,name,aggr,hp) #
self.kind = kind # 派生属性(父类没有的,子类有的属性)
def bite(self,person): # 派生方法(父类没有的,子类有的方法)
person.hp -= self.aggr
class Person(Animal):
def __init__(self,name,aggr,hp,sex):
Animal.__init__(self,name,aggr,hp)
self.sex = sex # 派生属性
self.money = 0 # 派生属性
def attack(self,dog):
dog.hp -= self.aggr
def get_weapon(self,weapon):
if self.money >= weapon.price:
self.money -= weapon.price
self.weapon = weapon
self.aggr += weapon.aggr
else:
print("余额不足,请先充值")
Liu = Dog('刘老板',20,500,'吉娃娃')
Liu.eat() #使用的继承父类animal的eat方法
print(Liu.hp) tong = Person('tong',1,2,None)
tong.eat() #使用的继承父类animal的eat方法
print(tong.hp) Liu.bite(tong) #使用Dog类自己的派生方法
print(tong.hp)

在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值.

在python3中,子类执行父类的方法也可以直接用super方法。

class A:
def hahaha(self):
print('A') class B(A):
def hahaha(self):
super().hahaha()
#super(B,self).hahaha()
#A.hahaha(self)
print('B') a = A()
b = B()
b.hahaha()
super(B,b).hahaha()

 总结:

  • 父类中没有的属性 在子类中出现 叫做派生属性
  • 父类中没有的方法 在子类中出现 叫做派生方法
  • 只要是子类的对象调用,子类中有的名字 一定用子类的,子类中没有才找父类的,如果父类也没有报错
  • 如果父类、子类都有,使用子类的
  •      如果还想用父类的,单独调用父类的
  •      父类名.方法名,需要自己传self参数
  •      super().方法名,不需要自己传只在新式类中有,python3中所有类都是新式类
  • 正常的代码中,单继承 === 减少了代码的重复
  • 继承表达的是一种 子类是父类的关系
class Animal:
def __init__(self,name,aggr,hp):
self.name = name
self.aggr = aggr
self.hp = hp
def eat(self):
print('吃药回血')
self.hp+=100
class Dog(Animal):
def __init__(self,name,aggr,hp,kind):
super().__init__(name,aggr,hp) #等价于Animal.__init__(self,name,aggr,hp),不需要传self
self.kind = kind # 派生属性(父类没有的,子类新增的属性)
Liu = Dog('刘老板',20,500,'吉娃娃')
Liu.eat() #使用的继承父类animal的eat方法
print(Liu.hp)

super()可以在类内使用,也可以在类外使用。

  • super()在类内使用:不需要传默认参数,就是类名和self
  • super()在类外使用:必须传类名和对象名
#super()在类外和类内
class Animal:
def __init__(self,name,aggr,hp):
self.name = name
self.aggr = aggr
self.hp = hp
def eat(self):
print('吃药回血')
self.hp+=100
class Dog(Animal):
def __init__(self,name,aggr,hp,kind):
super().__init__(name,aggr,hp) #等价于Animal.__init__(self,name,aggr,hp)
self.kind = kind # 派生属性(父类没有的,子类新增的属性)
def eat(self):print("dog eating")
Liu = Dog('刘老板',20,500,'吉娃娃')
print(Liu.name)
Liu.eat() # 执行的是Dog类里面的def eat(self):print("dog eating")
super(Dog,Liu).eat() # 执行的是父类里面的def eat(self):

二、多继承

class A:
def func(self):print("A")
class B:
def func(self):print("B")
class C:
def func(self):print("C")
class D(A,B,C): # D类继承A,B,C,多继承
def func(self):print("D") d = D()
d.func() #此时调用的D类的func()

class A:
def func(self):print("A")
class B:
def func(self):print("B")
class C:
def func(self):print("C")
class D(A,B,C): # D类继承A,B,C,多继承
pass
#def func(self):print("D") d = D()
d.func() #此时调用的A类的func(),因为class D(A,B,C),A类离D最近

2.1 多继承---经典案例----菱形继承(钻石继承)

B、C继承A,D继承B、C

class A:
def func(self):print("A")
class B(A): # B类继承A
def func(self):print("B")
class C(A): # C类继承A
def func(self):print("C")
class D(B,C): # D类继承B,C
pass
#def func(self):print("D") d = D()
d.func()

class A:
def func(self):print("A")
class B(A): # B类继承A
pass
#def func(self):print("B")
class C(A): # C类继承A
def func(self):print("C")
class D(B,C): # D类继承B,C
pass
#def func(self):print("D") d = D()
d.func()

class A:
def func(self):print("A")
class B(A): # B类继承A
pass
#def func(self):print("B")
class C(A): # C类继承A
pass
#def func(self):print("C")
class D(B,C): # D类继承B,C
pass
#def func(self):print("D") d = D()
d.func()

同理以下两个问题,继承顺序如下图:

2.2  总结

多继承中,我们子类的对象调用一个方法,默认是就近原则,找的顺序是什么?

  • 经典类中 深度优先
  • 新式类中 广度优先

① python2.7 新式类和经典类共存,新式类要继承object

② python3 只有新式类,默认继承object

③ 经典类和新式类还有一个区别:mro方法只在新式类中存在,类名.mro方法,查看广度优先的继承顺序。

④ super 只在python3中存在

⑤ super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的

class A(object):
def func(self): print('A') class B(A):
def func(self):
super().func()
print('B') class C(A):
def func(self):
super().func()
print('C') class D(B,C):
def func(self):
super().func()
print('D') b = D()
b.func()  

......

自学Python5.5-面向对象三大基本特征_继承的更多相关文章

  1. 自学Python5.7-面向对象三大基本特征_封装

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  2. 自学Python5.6-面向对象三大基本特征_多态

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  3. python 面向对象三大特性(封装 多态 继承)

    今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面 ...

  4. 【java基础】面向对象的三大基本特征之-------继承

    面向对象的三大特征:封装,继承,多态 java通过extends关键字来实现继承,而且是单继承,一个子类只可以有一个直接父类,但是父类还可以有父类... java.long.Object是所有类的父类 ...

  5. [Java入门笔记] 面向对象三大特征之:继承

    理解什么是继承 首先我们知道,面对对象有三大特征: 封装:解决了数据的安全性问题 继承:解决了代码的重用问题 多态:解决了程序的扩展问题 上一篇博客中,我们了解了一下封装,现在我了再来看看什么是继承. ...

  6. Python面向对象三大特性(封装、继承、多态)

    封装 类中把某些属性和方法隐藏起来,或者定义为私有,只在类的内部使用,在类的外部无法访问,或者留下少量的接口(函数)供外部访问:从上一篇文章中的私有属性与私有方法中的代码体现了该特性. class m ...

  7. OOP面向对象 三大特征 继承封装多态

    OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ...

  8. Java中面向对象三大特征

    也就是说在这里"人"是多态的, 在不同的形态时,特征行为是不一样的, 这里的"人", 同时有两种形态,一种是教师形态,一种是学生形态,所对应的特征行为分别是&q ...

  9. java中的面向对象的三大基本特征

    转载,原文来自http://blog.sina.com.cn/s/blog_5f79a56a0100c6ig.html 众所周知,java中的面向对象的三大基本特征是:[封装].[继承].[多态] 一 ...

随机推荐

  1. 阶段3 3.SpringMVC·_05.文件上传_1 文件上传之上传原理分析和搭建环境

    分成几个部分 里面可能就包含文件上传的值 提交方式要改成post 第三个就是提供一个input file的文件选择域 新建项目 新建一个项目 当前项目没有父工程 跳过联网下载 改成02 构建 编译和目 ...

  2. SQL server 自增主键重新从1开始

    原文链接:http://blog.csdn.net/zhengjia0826/article/details/43149953 dbcc checkident('sys_common_switch', ...

  3. SAS数据挖掘实战篇【五】

    SAS数据挖掘实战篇[五] SAS--预测模型 6.1 测模型介绍 预测型(Prediction)是指由历史的和当前的数据产生的并能推测未来数据趋势的知识.这类知识可以被认为是以时 间为关键属性的关联 ...

  4. django 模板里面for循环和if常用的方法

    django 模板里面for循环常用的方法 {% for %} 允许我们在一个序列上迭代.与Python的for 语句的情形类似,循环语法是 for X in Y ,Y是要迭代的序列而X是在每一个特定 ...

  5. android webview 访问 https 页面

    在android 中利用webview 控件进行开发过程中,可能会遇到 webview 访问不了https://的页面如 https://www.google.com.hk 重写onReceivedS ...

  6. Xshell的使用以及常用命令

    工具/原料 Xshell 方法/步骤 打开软件,点击新建,在主机哪里写入要访问的ip地址,名称随意 点击文件之后,再点击打开: 就可以看到刚才新建的会话了: 点击连接,就会显示下面的画面,输入用户名, ...

  7. Java 虚拟机的运行模式

    这几天在读周志明老师的<深入理解JVM虚拟机> 讲到了 java的运行模式, 有mixed 模式 interpret模式还有compile模式.效果如下面所示 java -version ...

  8. Fiddle-常用设置和操作记录

    1.导出证书: 2.清空屏幕: 3.字段认识 4.保存会话: 5.解码

  9. Java第六周课堂示例总结

    一.如果一个类中既有初始化块,又有构造方法,同时还设定了字段的初始值,谁说了算? public class InitializeBlockDemo { /** * @param args */ pub ...

  10. PHP使用CURL抓取页面

    cURL的基本原理 curl是利用URL语法在命令行方式下工作的开源文件传输工具,他能够从互联网上获得各种各样的网络资源.简单来说,curl就是抓取页面的升级版. <?php //1.初始化,创 ...