python入门笔记——类和对象⑤(继承)
# python中展现面向对象的三大特征:封装、继承、多态
# 封装:把内容封装到某个地方以便后续的使用
# 对封装来说,其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容
# 继承:子可以继承父的属性和方法
# 爸爸有的儿子都有,儿子有的父亲不一定有
# 继承
class Animal1:# 其实一般的类默认继承object超类,但大多省略了
def eat(self):
print('Animal1吃')
pass
def drink(self):
print('Animal1喝')
pass
pass
# 在类名后面的括号内写的即为所继承的父类
class Cat(Animal1):
def miao(self):# 子类的独有方法实现
print('喵喵')
pass
pass
class Dog(Animal1):
def wang(self):# 子类的独有方法实现
print('汪汪')
pass
pass
d1 = Dog()
d1.eat()
d1.wang()
c1 = Cat()
c1.drink()
c1.miao()
# 继承的一大好处在于去除了不必要的代码重复
# 多继承:子类也可以继承两个或多个父类,如c继承a,b两个类,可以同时拥有a,b两个类的方法和属性
class Shenxian:
def fly(self):
print('神仙都会飞')
pass
pass
class Monkey:
def jump(self):
print('猴子都喜欢跳')
pass
pass
class Linghou(Shenxian,Monkey):
def changes(self):
print('灵猴会七十二变')
pass
pass
sunwukong = Linghou()
sunwukong.fly()
sunwukong.jump()
sunwukong.changes()
# 当多个父类当中存在相同方法的时候应该调用哪一个的问题
class D(object):
def eat(self):
print('d:eat')
pass
pass
class C(D):
def eat(self):
print('C:eat')
pass
pass
class B(D):
pass
class A(B,C):
pass
a = A()
a.eat()
# 这个例子的顺序是:因为A类本身没有eat方法,所以去其父类中找,首先寻找父类B,同样没有找到
# 接着去C中找,C中存在eat方法,故这里调用的是C中的eat方法
# 如果找完C后再找D中也没有,就会报错
# [这个例子]调用的寻找方法[类似]广度优先遍历,是一层一层过去找
# 但其实这个地方的调用方法比较复杂,似乎也根据python版本的不同和代码的复杂情况有所不同,故不赘述
# 建议在考虑类似情况的时候还是使用下面的__mro__魔术方法测试一下
print(A.__mro__)# python中自带的一种魔术方法,可以用__mro__方法来获取这个类的调用顺序
# 重写:在子类中若有一个与父类名字相同的方法,则子类中的方法会覆盖掉父类中同名的方法
# 如果父类的方法已经不满足子类的需要,那么子类就可以重写父类方法
class father:
def __init__(self,name,wine):
self.name = name
self.wine = wine
self.sex = '男'
def drink(self):
print('喝酒')
pass
pass
class son(father):
def __init__(self,name,wine):# 属于重写父类的init方法
father.__init__(self,name,wine)# 这两行即是下面注释提到的修改,而不是def __init__(self):这样来重写
# 经过这样的操作后,即可以使用父类中init定义的属性,但要记得调用时要传参
# 上面这句语句也可以这样写:
# super().__init__(name,wine)# super()即代表父类,但如果这样用就不用穿self了,super会自动搜索到实例对象
self.height = 180
# 可以继承父类里定义的属性,也可以在子类中扩展自己的属性
pass
def drink(self):
print('喝饮料')
print('{}喝饮料'.format(self.name))
pass
def __str__(self):
return '{}的性别:{}、身高:{}'.format(self.name,self.sex,self.height)
pass
son1 = son('我','葡萄酒')# 注意:如果在上面不修改的话,这里不传参的话会报错:
# TypeError: __init__() missing 2 required positional arguments: 'name' and 'wine'
# 因为子类是没有写出init方法的,所以仍旧默认使用父类的init方法,而父类的init方法中是有传参
# 故这里也要重写父类的init方法
# 但记住,如果你仅仅是用def __init__(self):重写父类的init方法,那也不能使用父类init方法中定义的属性了
# 如果仍要使用父类init方法中定义的属性,那么这里需要在上面的init重写部分做出修改
# 这个地方的讲述可能不大清楚,可以再仔细推敲思考
son1.drink()
print(son1)
# 再在这里强调一次:super即代表父类,可以搜索一下super关键字看看
# 菜鸟教程super详解网址:https://www.runoob.com/w3cnote/python-super-detail-intro.html
输出结果:
Animal1吃
汪汪
Animal1喝
喵喵
神仙都会飞
猴子都喜欢跳
灵猴会七十二变
C:eat
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
喝饮料
我喝饮料
我的性别:男、身高:180