一、继承
- 什么是继承:继承是一种关系,必须存在两个对象才能产生这个种关系,被继承的称为父,继承的一方成为子。在程序中继承指的是类与类之间的关系
- 为什么要使用继承:在生活中通过继承,子可以直接享受父提供内容。在程序中,通过继承可以直接使用父类已有的代码
- 如何使用:在子类中加上括号,加上父类的名称即可,在python中一个子类可以有多个父类,多个父类在括号中用逗号隔开
class parent:
year = 2018
def coding(self):
print('正在编程')
pass
class sub(parent):
pass
print(parent.year)
print(sub.year)
s = sub()
#子类可以使用父类中的属性
print(s.year) #2018
#子类也可以用父类中的函数
s.coding() #正在编程
class Person:
def __init__(self ,name ,age ,sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
print("正在吃饭....")
def study(self):
print("正在学习....")
class Teacher(Person):
def teaching(self):
print("老师正在上课......")
t1 = Teacher("blex" ,30 ,"woman")
t1.eat() #正在吃饭....
t1.study() #正在学习....
class Student(Person):
pass
stu1 = Student("张三" ,20 ,"man")
stu1.eat() #正在吃饭....
stu1.study() #正在学习....
#通过继承避免了重复代码的编写
#通过抽象,避免了继承到一些不应该有的内容
#应该先抽象再继承,在抽取过程中,可能会一些跟业务需求无关的类,这是正常的这些称之为公共父类
#公共父类的作用是存储多个子类相同属性的技能
二、派生
- 什么是派生:派生指的是子类继承某个父类,并且拥有自己独特的属性或技能。该子类称之为派生类
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def sayHI(self):
print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
class Student(Person):
def __init__(self,name,age,sex,number):
self.name = name
self.age = age
self.sex = sex
self.number = number
# 上课
def attend_class(self):
print("%s 正在上课.....")
stu1 = Student('张三',19,'男','1')
print(stu1.number)
三、子类访问父类方法
方法1:
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
print(self)
def sayHI(self):
print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
class Student(Person):
def __init__(self,name,age,sex,number):
Person.__init__(self,name,age,sex)
self.number = number
def attend_class(self):
print('%s 正在上课'%(self.name))
def sayHI(self):
#指名道姓
#Person.sayHI(self)
super().sayHI()
print("学号:", self.number)
stu1 = Student("阿三",20,"woman","9527")
stu1.sayHI() #hello 我是阿三 今年20岁 性别:woman 学号: 9527
方法2:
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
print(self)
def sayHI(self):
print("hello 我是%s 今年%s岁 性别:%s" % (self.name,self.age,self.sex))
class Student(Person):
def __init__(self,name,age,sex,number):
self.number = number
# super() # 表示创建一个特殊的对象 用于调用父类的方法
super().__init__(name,age,sex)
# 了解:在python2中 super的使用方式有所不同 需要传入当前类,当前对象
#super(Student,self).__init__(name,age,sex)
# 上课
def attend_class(self):
print('%s 正在上课'%(self.name))
stu1 = Student("阿三",20,"woman","9527")
print(stu1.name,stu1.age,stu1.sex,stu1.number) #阿三 20 woman 9527
四、存在继承关系后的属性查找顺序
class S:
age = 17
def f1(self):
print("S f1")
class A(S):
pass
class B(A):
pass
b = B()
print(b.age) #17
总结:
查找顺序:对象==>类==>父类
优先查找对象,如果对象没有则找类,如果类没有,会沿着继承关系一直找到最顶层的父类
无论是属性还是方法,查找顺序是一样的
五 、存在多个父类时的查找顺序
class E:
a = 5
class A(E):
a = 4
pass
class B:
a = 3
pass
class C:
a = 2
pass
class D(A,B,C):
# a = 1
pass
d1 = D()
print(d1.a)
#按照继承的顺序,先继承谁就先找谁
class S:
a = 100
class A(S):
# a = 1
pass
class B(S):
# a = 2
pass
class C(S):
# a = 3
pass
class D(A):
# a = 4
pass
class E(B):
# a = 5
pass
class F(C):
# a = 6
pass
class G(D,E,F):
pass
g1 = G()
print(g1.a)
#显示属性的查找顺序列表
print(G.mro()) #[<class '__main__.G'>, <class '__main__.D'>, <class '__main__.A'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.F'>, <class '__main__.C'>, <class '__main__.S'>, <class 'object'>]
"""
s
a,b,c
d,e,f
g
"""
六、经典类型与新式类
-
什么是新式类:所有直接继承或间接继承object的类都是新式类,object 称之为根类 意思是所有类都源自于object类
-
为什么这么设计?例如:创建对象时,需要申请内存空间,创建新的名称空间,将对象的属性放入名称空间,这些复杂的基础操作都有Object来完成,所有的类都属于新式类(在python3中)
在python3中默认所有类都是新式类
而python2中默认是经典类(不会自动继承Object)
class S:
pass
class Student(S):
pass
#__bases__ 用于查看父类
print(Student.__bases__) #(<class '__main__.S'>,)
#显示属性的查找顺序列表,属性查找属性就是按照该列表来查找的
print(Student.mro())
七、super获取父类内容时按照mro列表查找
class S:
def f1(self):
print("s f1")
class A(S):
pass
class B(S):
def f1(self):
print("b f1")
pass
class C(A,B):
def f2(self):
print("c f2")
super().f1()
print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.S'>, <class 'object'>]
c1 = C()
c1.f2()
总结:super访问父类内容时,按照mro列表属性查找
八、覆盖
class A:
age = 18
def f1(self):
print("A f1")
pass
class B(A):
age = 19
def f1(self):
print("B f1")
b1 = B()
print(b1.age) #19
b1.f1() #B f1
总结:
子类出现了与父类重复的名字 称之为覆盖
子类出现了与父类不同的名字 称之为拍派生
小练习:
"""
设计王者荣耀中的英雄类,每个英雄对象可以对其他英雄对象使用技能
具备以下属性
英雄名称,等级,血量
和Q_hurt,W_hurt,E_hurt 三个属性,表示各技能的伤害量
具备以下技能
Q W E
三个技能都需要一个敌方英雄作为参数,当敌方血量小于等于0时输出角色死亡
"""
class Hero:
def __init__(self,name,level,hp,Q_hurt,W_hurt,E_hurt):
self.name = name
self.level = level
self.hp = hp
self.Q_hurt = Q_hurt
self.W_hurt = W_hurt
self.E_hurt = E_hurt
def Q(self,enemy):
enemy.hp -= self.Q_hurt
print("%s 对%s 释放了 %s 技能" % (self.name,enemy.name,"Q"))
print("造成了%s点伤害,剩余血量%s" % (self.Q_hurt, enemy.hp))
if enemy.hp <= 0:
print("%s被%s弄死了" % (enemy.name,self.name))
def W(self,enemy):
enemy.hp -= self.W_hurt
print("%s 对%s 释放了 %s 技能" % (self.name, enemy.name, "W"))
print("造成了%s点伤害,剩余血量%s" % (self.W_hurt,enemy.hp))
if enemy.hp <= 0:
print("%s被%s弄死了" % (enemy.name, self.name))
def E(self,enemy):
enemy.hp -= self.E_hurt
print("%s 对%s 释放了 %s 技能" % (self.name, enemy.name, "E"))
print("造成了%s点伤害,剩余血量%s" % (self.E_hurt, enemy.hp))
if enemy.hp <= 0:
print("%s被%s弄死了" % (enemy.name, self.name))
# 创建两个英雄
hero1 = Hero("小妲己",15,2000,50,500,600)
hero2 = Hero("小鲁班",15,1500,50,500,600)
hero1.Q(hero2)
hero1.W(hero2)
hero1.E(hero2)
hero1.E(hero2)