继承&方法重写&super用法&多重继承&多态

1.继承

  • 继承是面向对象的三大特性之一
    • 通过继承我们可以使一个类获取到其他类中的属性和方法
    • 在定义类时,可以在类名后面的括号中指定当前类的父类(超类、基类)
    • 继承提高了类的复用性,让类与类之间产生了关系,有了这个关系,才有了多态的特性
# 这是一个动物类
class Animal:
    def sleep(self):
        print('动物会睡觉')
    def run(self):
        print('动物会跑')
# 狗继承了动物这个类
class Dog(Animal):
    # pass  #  占位
    def speak(self):
        print('汪汪汪')
d.run()   # 动物会跑  继承了动物类中的方法
d.speak()  # 汪汪汪

# isinstance() 用于检查一个实例不是一个类的实例,如果是则返回True
print(isinstance(d,Animal))  # True  在这里Dog类继承了Animal类,则Dog的实例也是其父类的实例

# issubclass()  用于检查一个类是否是另一个类的子类,如果这个类是另一个类的子类,返回True
print(issubclass(Dog,Animal))  # True
print(issubclass(Dog,object))   # True
print(issubclass(Animal,object))  # True

2.方法的重写

  • 如果在子类中有和父类同名的方法,则通过子类实例去调用方法时,会调用子类的方法而不是父类的方法,这个特点我们称之为方法的重写(覆盖)
  • 当我们调用一个对象的方法时:
    • 会优先去当前对象中寻找是否具有该方法,如果有则直接调用
    • 如果没有,则去当前对象的父类中寻找,如果父类中有则直接调用父类中的方法
    • 如果没有,则去父类中的父类寻找,以此类推,直到找到object,如果依然没有找到就报错了
class A(object):
    def test(self):
        print('A')

class B(A):
    def test(self):
        print('B')

class C(B):
    pass

c = C()
c.test()  # B 当前C类中没有test方法,则去其父类B中寻找,发现有则调用

3.super继承

  • super()可以获取当前类的父类,并且通过super()返回对象调用父类方法时,不需要传递self
# 这是一个动物类
class Animal:
    def __init__(self,name):
        self._name = name

    def sleep(self):
        print('动物胡睡觉')

    def run(self):
        print('动物会跑')

    @property
    def new_name(self):
        print('new_name的get方法执行了')
        return self._name    # 返回的是一个值
        
    # setter方法  @属性名.setter
    @new_name.setter
    def new_name(self,name):
        print('new_name的set方法执行了')
        self._name = name

# 狗类继承了动物类
# 父类中所有的方法都会被继承,包括特殊方法
class Dog(Animal):
    def __init__(self,name,age):
        # self._name = name

        # Animal.__init__(self,name)  # 等价于self._name = name
        
        # super()可以用来动态获取当前类的父类,不需要传递self
        #(super(可以传self).__init__((此处不用传self)name))
        super().__init__(name)   # 等价于self._name = name
        self._age = age  # 这种类型只用于该类独有的,其余的父类中有的直接用上面super()就好
    @property
    def new_age(self):
        print('new_age的get方法执行了')
        return self._age    # 返回的是一个值

    # setter方法  @属性名.setter
    @new_age.setter
    def new_age(self,age):
        print('new_age的set方法执行了')
        self._age = age
    def speak(self):
        print('汪汪汪')

d = Dog('黑狗',5)
d.new_name = '田园犬'  # new_name的set方法执行了
d.new_age = 6   # new_age的set方法执行了
print(d.new_name,d.new_age)  # new_name的get方法执行了(因为d.new_name相当于调用了get方法),new_age的get方法执行了  田园犬 6

4.多重继承

4.1 简单继承

  • 1.在Python中是支持多重继承的。也就是我们可以为一个类同时制定多个父类
  • 2.可以在类名的()后边添加多个类,来实现多重继承
  • 3.多重继承,会使子类同时拥有多个父类,并且会获取到所有父类中的方法
  • 4.在开发中没有特殊情况,应该尽量避免使用多重继承。因为多重继承会让我们的代码更加复杂
  • 5.如果多个父类中有同名的方法,则会先在第一个父类中寻找,然后找第二个,找第三个…前面会覆盖后面的
class A(object):
    def test1(self):
        print('A中test1的方法')

class B(object):

    def test1(self):
        print('B中test1的方法')

    def test2(self):
        print('B')

class C(B):
    pass
c = C()
c.test1()  # B中test1的方法
# print(C.__bases__)  # (<class '__main__.B'>,)

class C(A,B):
    pass
c = C()
c.test1()  # A中test1的方法

# 在 python中是支持多继承的
# 类名.__bases__  这个属性可以获取当前类的所有父类
# print(C.__bases__)  # (<class '__main__.A'>, <class '__main__.B'>)

4.2 钻石继承问题(遵循广度优先)

例1:不含super()

class A:
    def func(self):
        print('A')
class B(A):
    pass
    def func(self):
        print('B')
class C(A):
    pass
    def func(self):
        print('C')
class D(B):
    pass
    def func(self):
        print('D')
class E(B,C):
    pass
    def func(self):
        print('E')
class F(D,E):
    pass
    def func(self):
        print('F')
f = F()
f.func() # F
print(F.mro())    # 广度优先的遍历顺序 简写为F->D->E->B->C->A

遍历顺序原则如下图示:
在这里插入图片描述

例2:含super(),此时需要采用子节点去寻找

class A:
    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')
 
d = D()
d.func()  # A C  B  D
print(D.mro())  # 遍历顺序简写为:D->B->C->A

**注:**这里的多继承是根据子节点去找的,执行d.func()的时候遇到super,去B中去找,B中也有Super,紧接着会去C,发现C也有super,由于广度优先,此时它会找到A,执行A,再返回C,执行C,再到B,再到D

遍历图示如下:
在这里插入图片描述

例3:简单介绍一下mro()的用法:

  • 这个方法用于返回某个类的基类以及基类的基类,我们举一个简单的例子:创建一个类A,然后调用mro,它返回了一个列表,列表元素是类A本身和它的基类
class A:
   def test(self):
        print('from A')
class B(A):
    def test(self):
        print('from B')
class C(A):
    def test(self):
        print('from C')
class D(A):
    def test(self):
        print('from D')
class E(B):
    def test(self):
        print('from E')
 
class F(E,D,C):
    def test(self):
       print('from F')
print(F.mro())  # F->E->B->D->C->A

图示如下:
在这里插入图片描述

例4:含super()的计算实例

class Init(object):
    def __init__(self,value):
        self.val = value
 
class Add2(Init):
    def __init__(self,val):
        super(Add2,self).__init__(val)
        self.val += 2
 
class Mul5(Init):
    def __init__(self,val):
        super(Mul5,self).__init__(val)
        self.val *=5
 
class Pro(Mul5,Add2):
    pass
 
class Incr(Pro):
    csup = super(Pro)
 
    def __init__(self,val):
        self.csup.__init__(val)
        self.val += 1
 
p = Incr(5)
print(p.val)  # 36   (5+2)*5+1=36

图示:
在这里插入图片描述
思路: 从Incr开始,有super(),找到Pro,Pro中没有__init__属性,故先去找父类Mu15,发现有super(),故再去Add2(),发现也有super(),由于广度优先,则会去找到Init(),执行操作,再返回执行Add2(),再执行Mu15(),最后执行Incr

广度优先图:

在这里插入图片描述

5.多态

  • 多态是面向对象的三大特性之一。从字面理解就是多种形态
    • 一个对象可以由不同的形态去呈现(参考len()函数的用法,该函数可以处理不同类型的对象)
  • 面向对象三大特性
    • 封装 确保对象中数据的安全
    • 基础 保证了对象的扩展性
    • 多态 保证了程序的灵活性
# len()函数的用法
# len()函数之所以可以获取长度,是因为对象中有一个特殊方法 __len__
list = [1,2,3]
str = 'python'
print(len(list)) # 3
print(len(str))  # 6
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值