python进阶03 继承

一、继承

  课堂练习:假设你正在参与一个魔幻类角色游戏的开发,公司需要腻味这个游戏设计两个角色的类:

  a、剑士

    属性:1、角色名;2、角色等级;3、生命值;4、攻击力

    行为:物理攻击

  b、法师

    属性:1、角色名;2、角色等级;3、生命值;4、法术强度

    行为:1、法术攻击;2、治疗

#首先定义一个剑士类
class SwordsMan:#定义一个剑士类
def __init__(self,name,lever,blood): #初始化剑士的名字,等级,血量
self.name=name
self.lever=level
self.blood=blood def fight(self): #行为函数 攻击方式:物理攻击
print('物理输出') def __repr__(self): #str没有的时候会找repr
return '{cls}{name}{level}{blood}'.format(cls=__class__.__name__,name=self.name,level=self.level,blood=self.blood) #cls=__class__.__name__表示不管当前是哪个类,用这种方法就可以输出类名(好处在于不用指定类名,让系统自己算出自己的类名)
#然后定义一个法师类
class Magician:#定义一个法师类
def __init__(self,name,lever,blood): #初始化剑士的名字,等级,血量
self.name=name
self.lever=level
self.blood=blood def fight(self): #行为函数 攻击方式:物理攻击
print('法术攻击') def cure(self):#行为函数 治疗
print('治疗') def __repr__(self): #str没有的时候会找repr
return '{cls}{name}{level}{blood}'.format(cls=__class__.__name__,name=self.name,level=self.level,blood=self.blood)

  两个类中有大量重复的代码,是否可以只写一次(两个类之间有交集)

  剑士和法师都是角色,那么我们可以定义一个剑士和法师都隶属的角色类

class Role:#
def __init__(self,name,lever,blood):
self.name=name
self.lever=level
self.blood=blood def fight(self):
raise NotImplementedError('攻击方式没有实现')#raise:自己丢出异常(认为异常/自己丢出异常);NotImplementedError:表示必须要在子类中去实现,Not表示没有 implemented表示实现 def __repr__(self):
return '{cls}{name}{level}{blood}'.format(cls=__class__.__name__,name=self.name,level=self.level,blood=self.blood)

  然后就是继承,就是从角色类中派生(也就是继承)出各自的类

class SwordsMan(Role): #如果什么都不写,就是跟父类Role一模一样
pass #剑士类 class SwordsMan(Role):
def init(self,name,level,blood,attack_power):
Role.__init__(self,name,level,blood) #这样手动调一次父类中已经定义的东西,公共的部分父类帮你初始化,子类的部分自己定义
self.attack_power=attack_power def fight(self):#父类里面有的,子类里面再写一次,叫做重写
print('物理攻击') #同理 法师
class Mgician(Role):
def init(self,name,level,blood,attack_power):
Role.__init__(self,name,level,blood)
self.magic_power=magic_power def fight(self):
print('魔法攻击') def cure(self):
print('治疗')

  继承搜索

#访问类的属性和方法-->类 (如果找不到,转到其父类中查找) -->直接基类(如果再找不到,转到其父类的父类中去查找)-->间接基类

#所以继承不是变量空间的复制

#属性查找
class Role:
pass class MyRole(Role):
pass print(MyRole.__dict__) #查找MyRole #在子类中查找到了init,父类中的init就会被屏蔽

  关于重用父类的init

class SwordsMan(Role):

    def init(self,name,level,blood,attack_power):#子类中查找的self是剑士的实例
Role.__init__(self,name,level,blood) #在父类中查找出的self也是剑士的实例
self.attack_power=attack_power #相当于
def __init__(self,name,level,blood,attack_power):
self.name=name
self.level=level
self.blood=blood
self.attack_power=attack_power

  顶级基类object:所有类最终的父类,类似于树的跟

#假如我拿到了别人写的库或者框架
#人家肯定用到了面向对象,肯定会有继承
#我正在用这个类,我想了解他的继承关系,想知道它继承于什么类 print(Magician.__bases__) #输出(Role)查找Magician类继承于什么类

  继承的意义:重用代码,方便代码的管理和修改

二、多重继承

  如果有多个基类,有同名属性和方法,应该如何选择

class D:
pass class E:
pass class C:
pass class B(D,E): #B继承于D,E
pass class A(B,C):
pass

#到底是广度查找(A B C A E)还是(A B D E C)
#不是以上两种方法,而是MRO-C3算法 print(A.mro()) #mro方法,是在类里面的,它会自己计算出,搜索顺序

  C3算法会由于冲突导致不能继承

class A:
pass class B:
pass class C(A,B):
pass class D(B,A):
pass class E(C,D):
pass #会报错,这个顺序是违反了C3规则
#对于C而言,A比B优先;对于D而言,B比A优先,而E继承C和D就爆炸了

  鸭子类型:如果走起来或叫起来像鸭子,那么你就是鸭子

class SwordsMan(Role):
def init(self,name,level,blood,attack_power):
Role.__init__(self,name,level,blood)
self.attack_power=attack_power def fight(self):
print('物理攻击') #展示出攻击的效果(这件事不属于任何一个角色)
#写一个函数
def draw_fight(role): #鸭子类型体现出来的是,一个函数关心的不是类型,而是行为
print('role',end='')
role.fight() #要求你传入一个Role,传入剑士的实例可以吗?可以。因为剑士也是角色,我不管你是什么类,只要你有fight方法,我就认为你是个角色 s=SwordsMan('A',18,3000,8888)
draw_fight(a) #输出role 物理攻击 class Girlfriend: def __init__(self,name):
self.name=name def fight(self):
print('拔电源攻击') g=Girlfriend('xiaopo')
draw_fight()#输出role 拔电源攻击 综上鸭子类型,只要你有这个行为,你就是鸭子

  基于多继承的Mix-in设计模式

#单继承就是分类思想,爸爸就只有一个,往下无限繁衍
#多继承就是拼积木(Mix-in)思想
#注意:一般“Mix-in”是继承的终点,只继承一次,通俗的讲:就是胳膊有人这个爸爸,脑袋有人这个爸爸,腿有人这个爸爸,这三个最好不要有其他爸爸,人上面也别在生出个爸爸

三、super函数

 更加优雅地调用父类中的方法

#在角色和剑士中间加了两个分类:英雄和NPC,怎么办
class Hero:
pass class NPC:
pass class SwordsMan(Role):
def init(self,name,level,blood,attack_power):
Role.__init__(self,name,level,blood) #如果我在做游戏,Role只是角色,角色又可以分为英雄和NPC。这便需要将Role变为Hero,也就是在调用父类方法的时候要变为Hero了,上面类中的Role也要换,这样很不优雅
self.attack_power=attack_power 改变为下面这个即可:
class SwordsMan(Role):
def init(self,name,level,blood,attack_power):
super().__init__(name,level,blood) #将前面的Role变为super,后面的self去掉,系统会自动查找父类
self.attack_power=attack_power

python进阶03 继承的更多相关文章

  1. Python面向对象03 /继承

    Python面向对象03 /继承 目录 Python面向对象03 /继承 1. 初识继承 2. 单继承 3. 多继承 4. 总结 1. 初识继承 概念:专业角度:如果B类继承A类,B类就称为子类,派生 ...

  2. python进阶03

    进程线程不管哪门语言都是一块可以被重视的方向,下面一起学习学习python中的进程,线程 1.进程线程区别 通俗解释:一个程序QQ的运行就是一个进程运行:QQ中打开多个页面互不影响可以同时操作的每个页 ...

  3. Python进阶-XVI 继承 单继承 多继承

    一.初识继承 1.引入继承 class A(object): pass # 父类,基类,超类 class B: pass # 父类,基类,超类 class A_son(A, B): pass # 子类 ...

  4. Python进阶03 模块

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们之前看到了函数和对象.从本质上来说,它们都是为了更好的组织已经有的程序,以方便 ...

  5. Python进阶-继承中的MRO与super

    Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...

  6. python进阶(5):组合,继承

    前两天我们认识了面向对象也对面向对象有了初步的认识今天我们先会说一点组合的进阶,今天重点是继承. 一.组合 组合只有一个例子因为组合只作为上一章的补充内容 #老师 课程 生日 class Course ...

  7. Python类的继承(进阶5)

    转载请标明出处: http://www.cnblogs.com/why168888/p/6411918.html 本文出自:[Edwin博客园] Python类的继承(进阶5) 1. python中什 ...

  8. Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)

    Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理) 一丶封装 , 多态 封装:            将一些东西封装到一个地方,你还可以取出来( ...

  9. Python进阶(十五)----面向对象之~继承(单继承,多继承MRO算法)

    Python进阶(十五)----面向对象之~继承 一丶面向对象的三大特性:封装,继承,多态 二丶什么是继承 # 什么是继承 # b 继承 a ,b是a的子类 派生类 , a是b的超类 基类 父类 # ...

随机推荐

  1. Use trained sklearn model with pyspark

    Use trained sklearn model with pyspark   from pyspark import SparkContext import numpy as np from sk ...

  2. 数据可视化入门之show me the numbers

           数据的可视化一直是自己瞎玩着学,近来想系统的学数据可视化的东西,于是搜索资料时看到有人推荐<show me the numbers>作为入门. 由于搜不到具体的书籍内容,只能 ...

  3. arm-linux-gcc4.4.3编译s3c2410平台linux内核

    写在前面:2.6.14版本的内核用arm-linux-gcc4.4.3没有编译成功,下载2.6.37版本的内核用arm-linux-gcc4.4.3编译通过. 一.首先下载linux内核: linux ...

  4. MySQL上周新增激活用户在上周下单情况_20161107周一

    上周新增激活用户在上周下单情况 1.上周激活用户明细 #上周激活用户明细 SELECT a.城市,a.用户ID,a.用户名称,b.用户地址,b.联系电话,a.订单日期,c.年周,c.上周一,a.订单I ...

  5. <十六>UML核心视图动态视图之状态图

    一:状态图 --->状态图显示一个状态机. --->状态机用于对模型元素的动态性进行建模.更具体地说,就是对系统行为中受事件驱动的方面进行建模. --->通常使用状态图来说明业务角色 ...

  6. python爬虫知识点总结(十)分析Ajax请求并抓取今日头条街拍美图

    一.流程框架

  7. 误删除$ORACLE_HOME/dbs下的参数文件、密码文件,如何快速重建

    [oracle@11g dbs]$ pwd/home/oracle/app/oracle/product/11.2.0/dbhome_1/dbs[oracle@11g dbs]$ lltotal 24 ...

  8. poj2411铺砖——状压DP

    题目:http://poj.org/problem?id=2411 状态压缩,一行的状态记为一个二进制数,从上往下逐行DP,答案输出最后一行填0的方案数. 代码如下: #include<iost ...

  9. SQL Server 将查询的结果生成insert语句

    1.将查询的结果插入到一张新表(yangTest 表系统会自动生成)select Area, District, RoadName, StationName, PathDirection, Stati ...

  10. 网络编程 recv()函数

    recv()是编程语言函数. 函数原型int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags); 这里只描述同步S ...