继承是创建新类的方式,新建的类可以继承多个父类(python里),父类又称为基类和超类,新建的类又称为派生类和子类
如果没有基类,python默认继承object祖类,object是所有类的基类
一、继承分为单继承和多继承
class Animal:pass #父类 超类 可以有Cat Dog两个子类
class Cat(Animal):pass # 单继承:只继承一个父类,
class Dog(Cat,Animal):pass # 多继承:可以继承多个父类
二、查看继承
class Animal:
def d(self):pass
class Cat(Animal):
def func(self):pass
class Dog(Cat,Animal):pass
print(Dog.__base__) #
print(Dog.__bases__) #(
三、继承与抽象(先抽象再继承)
抽象是抽取类似或者比较像的部分:比如周杰伦,蔡依林抽象为人, 金毛,泰迪抽象为狗 最后人和狗都抽象为动物,通过抽象得到类
继承是基于抽象的结果,通过继承的方式去表达出抽象的
那么问题来了什么时候会用到继承呢?有这样一段代码
class Cat:
def __init__(self,name,sex,color,eat):
self.c_name=name
self.c_sex=sex
self.c_color=color
self.c_eat=eat
def beauty_cat(self):
return '%s喜欢吃%s'%(self.c_name,self.c_eat)
class Dog:
def __init__(self,name,sex,color,eat,age):
self.c_name = name
self.c_sex = sex
self.c_color = color
self.c_eat = eat
self.c_age = age
def duty_dog(self):
return '%s是%s毛色'%(self.c_name,self.c_color)
mimi=Cat('mimi','女','white','fish')
tide=Dog('tide','男','dark','meat',2)
print(mimi.beauty_cat())
print(tide.duty_dog())
这时候我们发现猫和狗的属性惊人的相似,这么冗余的代码我们怎么能忍受!这时候我们想到了继承,首先抽象出一个父类Animal
然后让cat dog 继承Animal 解题如下:
class Animal: # 定义父类,抽象出一致的属性:name,sex,color,eat
def __init__(self, name, sex, color, eat):
self.c_name = name
self.c_sex = sex
self.c_color = color
self.c_eat = eat
class Cat(Animal):
def beauty_cat(self): # 猫的属性和父类Animal完全一致,就可以不用写属性,自己没有的会自动找父类调用
return '%s喜欢吃%s' % (self.c_name, self.c_eat)
class Dog(Animal):
def __init__(self, name, sex, color, eat, age): # Dog有自己独有的属性age,所有需要init再定义一个自己独有的属性age,
Animal.__init__(self, name, sex, color, eat) # 并且要把共有的 name, sex, color, eat属性都传进去,但是自己没有定义这些共有属性,需要调用父类的init
super().__init__(name, sex, color, eat) #super()实现的功能和Animal.__init__(self, name, sex, color, eat)一样,可以不用再传self,而且会自动找父类
self.age = age # 派生属性 # 所以在这里需要调用Animal.__init__(),并把父类的参数一并传进去
def duty\_dog(self): # 派生方法
return '%s是%s毛色' % (self.c\_name, self.c\_color)
mimi = Cat('mimi', '女', 'white', 'fish')
tide = Dog('tide', '男', 'dark', 'meat', 2)
print(mimi.beauty_cat())
print(tide.duty_dog())
小结:
# 继承:
"""
继承的作用:减少代码的重用
提高代码可读性
规范编程模式
1.可以提高代码的复用性
2.一个类 可以被多个类继承
3.一个类 可以继承多个父类 —— python里
"""
"""
1.子类也可以自己新增一些自己独特属性,但是如果名字和父类的是名字重复,那么调用新增属性的时候,会先以自己定义的为准
2.父类中没有的属性 在子类中出现 叫做派生属性
3.父类中没有的方法 在子类中出现 叫做派生方法
"""
"""
1.子类对象的调用,如果子类有的先用自己的,自己没有的再找父类的,父类没有就报错
2.父类名.方法名()调用父类中的init,但是需要自己传self
3.super() 不用自己传self,功能同上
"""
"""
1.正常的代码中 用单继承 === 减少了代码的重复
2.继承表达的是一种 子类是父类的关系 记住是————'是'————的关系,以后看到谁是谁的,就要想到可不可以用继承,eg教授是老师
3.之前的组合是表示————'有'————的关系 eg:老师有生日,
"""
继承进阶练习:人狗大战,人加武器
class Dog:
def __init__(self, name, aggr, hp, kind):
self.name = name
self.aggr = aggr
self.hp = hp
self.kind = kind
def bite(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):
dog.hp -= self.aggr
def get\_weapon(self, weapon):
if self.money >= weapon.w\_price:
self.money -= weapon.w\_price
self.weapon = weapon
self.aggr=weapon.w\_aggr
else:
print('余额不足,请充值')
class Weapon:
def __init__(self, name, aggr, njd, price):
self.w_name = name
self.w_aggr = aggr
self.w_njd = njd
self.w_price = price
def hand\_w(self, dog):
if self.w\_njd > 0:
dog.hp -= self.w\_aggr\*2
self.w\_njd -= 1
tide = Dog('tide',100,200,'咬人')
join = Person('join',50,10,'打狗')
shoot = Weapon('shoot', 20, 3, 500)
join.money += 1000
join.get_weapon(shoot)
join.attack(tide)
print(join.hp) #
print(tide.hp) #
shoot.hand_w(tide)
print(join.hp)
print(tide.hp)
原版
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):
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.w\_price:
self.money -= weapon.w\_price
self.weapon = weapon
self.aggr=weapon.w\_aggr
else:
print('余额不足,请充值')
class Weapon:
def __init__(self, name, aggr, njd, price):
self.w_name = name
self.w_aggr = aggr
self.w_njd = njd
self.w_price = price
def hand\_w(self, dog):
if self.w\_njd > 0:
dog.hp -= self.w\_aggr\*2
self.w\_njd -= 1
tide = Dog('tide',100,200,'咬人')
join = Person('join',50,10,'打狗')
shoot = Weapon('shoot', 20, 3, 500)
join.money += 1000
join.get_weapon(shoot)
join.attack(tide)
print(join.hp) #
print(tide.hp) #
shoot.hand_w(tide)
print(join.hp)
print(tide.hp)
继承版
四、新式类中的继承顺序
广度优先,尽量不错过所有继承的类,由于BC都继承了A类,所以在注释了B 类之后,系统会感知到
C类也继承了A,最终从C类,也会找到A类,为了不遗漏C,所以从广度来说在注释了B 类之后,会先执行C类的程序。
新式类 继承object类的才是新式类 广度优先
class A:
def func(self):
return '你好'
class B(A):pass
def func(self):
return '我好'
class C(A):pass
def func(self):
return '大家好'
class D(B,C):pass
def func(self):
return '人人好'
先实例化一个join 调用jion.func
#第一种 情况,自己有func,先执行自己的 打印出‘人人好’
join=D()
print(join.func()) #人人好
#第二种情况,注释掉D类中的func,写上pass,会根据广度优先找到最近继承的B类,打印B类中的‘我好’
print(join.func()) #我好
#第三种情况,注释掉B类中的func,写上pass,会根据广度优先找到最近继承的C类,打印C类中的‘大家好’
print(join.func()) #大家好
print(join.func()) #'你好'
砖石继承顺序
class A:
def func(self):
return '你好'
class B():pass
def func(self):
return '我好'
class C(B):pass
def func(self):
return '大家好'
class D(A):pass
def func(self):
return '人人好'
class E(C,D):pass
def func(self):
return '不好'
先实例化一个join 调用jion.func
#第一种 情况,自己有func,先执行自己的
join=E()
print(join.func()) #不好
#第二种情况,注释掉E类中的func,写上pass,会根据广度优先找到最近继承的C类,
print(join.func()) #大家好
#第三种情况,注释掉C类中的func,写上pass,会根据广度优先找到最近继承的B类,打印B类中的‘我好’
print(join.func()) #我好
#第四种情况,注释掉B类中的func,写上pass,会根据广度优先找到最近继承的D类,打印A类中的'人人好'
print(join.func()) #人人好
#第五种情况,注释掉D类中的func,写上pass,会根据广度优先找到最近继承的A类,打印A类中的'你好'
print(join.func()) #你好
进阶继承
ass 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() #打印顺序是A C B D
pr
查看继承的顺序 mro 还有super
五、经典类 如果你直接创建一个类在2.7中就是经典类 深度优先
**六、小结
**
#小结:
'''
单继承 子类有的就用自己的,没有就用父类的
多继承 就近原则,顺序是:新式类广度优先;经典类深度优先
py2中 新式类和经典类共存,但是新式类要继承object
py3中只有新式类
mro 查看继承的顺序
super 本质不是单纯的找父类,而是根据调用者的节点位置的广度优先顺序来的
'''
手机扫一扫
移动阅读更方便
你可能感兴趣的文章