继承与派生
首先补充知识点: 类内 定义一个变量是为了要去用 如果没有用的必要 就无需写
还有程序中的类 并不完全等同于现实生活中的类(程序中可以定义现实生活中不存在的类)
今天我们讲了继承与派生:
首先我们先来了解一下什么是继承?
继承是一种新建类的方式,在python中支持一个儿子继承多个类,新建的类称为子类或者派生类,父类又可以称为基类或者超类,子类为‘遗传‘父类的属性
知道了什么是继承,我们就要知道它是干什么用的,很简单就是减少代码的冗余
继承的用法:
# 继承的用法? class 爹: pass class 干爹: pass class 儿子(爹,干爹): pass #如果想查看儿子有多少个爹 print(儿子.__bases__) (<class '__main__.爹'>, <class '__main__.干爹'>)
继承的用法简单粗暴的说就是 把子类中需要重复使用的代码总结到父类中,需要的话就去里面调用(其实继承的用法有点相似与目录开发规范中lib的用法)
举个简单的例子
# 继承的实际运用
class LoL:
def __init__(self,name,aggressivity ,hp):
self.name=name
self.aggressivity=aggressivity
self.hp=hp
class AD(LoL):
def info(self):
print('%s射手英雄,她的攻击力为%s,血量为%s'%(self.name,self.aggressivity,self.hp))
class AP(LoL):
def info(self):
print('%s法师英雄,她的攻击力为%s,血量为%s'%(self.name,self.aggressivity,self.hp))
ad=AD('vn',85,450)
ap=AP('ez',60,450)
ad.info()
ap.info()
继承是类与类直接的关系,寻找这种关系需要先抽象再继承
上面我们列举了 射手英雄 和 法师英雄的例子,那么我们现在就遇到了一个问题,法师英雄不光有物理攻击 还要有法术伤害 那我们应该如何为法师添加上他的法术攻击那!!!
我们就需要用到派生;
派生:子类定义自己的新属性。如果与父类同名,以子类为准
子类派生的新方法中重用父类的功能
这样我们就会想到既然以子类为准我们就在子类中重新添加一边法师的所有属性不就好了嘛!!!这是个错误的想法,继承的作用就是 减少代码冗余 如果重新添加 那不又形成了代码冗余嘛,所以下面要介绍两种派生的正确用法:
方式一:指名道姓地调用(与继承是没有关系的)
方式二:super()调用(严格依赖于继承关系)
# 派生的用法 # 方式一:指名道姓 class LoL: def __init__(self,name,aggressivity ,hp): self.name=name self.aggressivity=aggressivity self.hp=hp class AD(LoL): print('%s射手英雄,她的攻击力为%s,血量为%s') class AP(LoL): def __init__(self,name,aggressivity ,hp,magic): LoL.__init__(self,name,aggressivity,hp) self.magic=magic print('%s法师英雄,她的攻击力为%s,血量为%s') ad=AD('vn',85,450) ap=AP('ez',60,450,90) print(ap.__dict__)#{'name': 'ez', 'aggressivity': 60, 'hp': 450, 'magic': 90} #方式二super()调用(严格依赖于继承关系) class LoL: def __init__(self,name,aggressivity ,hp): self.name=name self.aggressivity=aggressivity self.hp=hp class AD(LoL): print('%s射手英雄,她的攻击力为%s,血量为%s') class AP(LoL): def __init__(self,name,aggressivity ,hp,magic): super().__init__(name,aggressivity ,hp) self.magic=magic print('%s法师英雄,她的攻击力为%s,血量为%s') ad=AD('vn',85,450) ap=AP('ez',60,450,90) print(ap.__dict__)#{'name': 'ez', 'aggressivity': 60, 'hp': 450, 'magic': 90}
super()的返回值是一个特殊的对象,该对象专门用来调用父类中的属性
属性查找
# 继承的属性查找 # 查找顺序: # 自己--->类--->父类--->object # 在这我们要说一个概念:class 爹:的父类默认为object即class 爹(object): # 自己--->类 找到了bar f1 class foo: def f1(self): print('foo f1') class bar(foo): def f1(self): print('bar f1') obj=bar() obj.f1()#bar f1 # 自己--->类--->父类 找到了foo f1 class foo: def f1(self): print('foo f1') class bar(foo): def f2(self): print('bar f1') obj=bar() obj.f1()#foo f1 # 通过下面的例子检测你是否明白了属性查找 class foo: def f1(self): print('foo f1') def f2(self): print('foo f2') self.f1() class bar(foo): def f1(self): print('bar f1') obj=bar() obj.f2()
了解知识点,只需要记住结论!!!
在python2中分为:经典类和新式类(在2中,通过有木有加(object)来判断是什么类,有则是新式类)
在python3中:只有新式类
属性查找
在菱形继承的背景下:
经典类是深度优先
新式类是广度优先