Python 面向对象---继承

目录

 

一、继承的概念

1,继承的作用:

2,继承的格式

二、方法的复写以及使用

1,子类定义了和父类相同的方法

2,复写的条件:

3,调用方法的顺序

4,super() 方法

5, __init__() 方法

三、派生属性 / 属性的覆盖

四,私有方法和私有属性在继承中的体现

五、抽象类

1,抽象类概述:

2,格式:

第一种:from abc import ABCMeta,abstractmethod

第二种:import abc

六、多继承

1,概念

2,注意事项:

(1)  如果一个子类继承的多个父类中有相同的方法,子类该如何继承父类的方法呢?

(2)  类的搜索路径的查找顺序:

七、继承原理 / 钻石原理

八、多继承中的 super() 本质


一、继承的概念

让类和类之间产生父子关系,让子类可以拥有父类的属性和方法,但不能继承私有属性

继承就是可以获取另一个类中的静态属性和普通方法

1,继承的作用:

提高代码的重用率

2,继承的格式

class 子类名(父类名):

      .....代码....

      .....代码.....

所有的类都默认继承object类

描述 举例
新式类(主要使用) 把默认继承的object类写出来 class Animal(object):
旧式类 不用把默认继承的object类写出来 class Animal(object):

 

 

 

 

二、方法的复写以及使用

1,子类定义了和父类相同的方法

2,复写的条件:

当父类的方法不满足子类的需求的时候,就使用方法的复写

3,调用方法的顺序

先去子类里面找,找不到再去父类,父类里面找不到就报错

class Animal(object):
    type = '动物'
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def eat(self):
        print('吃...')
 
    def sleep(self):
        print('睡觉...')
 
 
class Dog(Animal):
    def eat(self):
        print('吃狗粮...')
 
    def look_door(self):
        print('看大门...')
 
 
class Cat(Animal):
    def eat(self):
        print('吃小鱼...')
 
    def climb(self):
        print('爬树...')
 
 
dog = Dog('京东狗', 8)
dog.eat()  # 吃狗粮...
dog.sleep()  # 睡觉...
dog.look_door()  # 看大门...
cat = Cat('天猫', 10)
cat.eat()  # 吃小鱼...
cat.sleep()  # 睡觉...
cat.climb()  # 爬树...

4,super() 方法

当子类和父类有相同的方法的时候,子类默认调用自己的方法,不能使用父类的方法。

如果想要使用父类的方法,我们就可以用super() 方法来调用父类的方法

super() 使用格式
子类内部用 外部用
super().方法()  
super(子类名,self).方法() super(子类名.子类对象名).方法()
父类名.方法(self) 父类名.方法(子类对象名)

 

 

 

 

 

class Animal(object):
    type = '动物'
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def eat(self):
        print('吃')
 
    def sleep(self):
        print('睡觉...')
 
 
class Dog(Animal):
    def look_door(self):
        print('看大门...')
 
    def eat(self):
        super().eat()  # 调用父类的eat()方法
        super(Dog, self).eat()  # super(子类名,self).方法()
        Animal.eat(self)  # 父类名.方法(self)
        print('吃狗粮...')
 
 
dog = Dog('京东狗', 8)
super(Dog, dog).eat()  # super(子类名,子类对象名).方法()
Animal.eat(dog)  # 父类名.方法(子类对象名)
dog.eat()

5, __init__() 方法

(1).如果子类不复写 __init__() 方法,就会自动调用父类的 __init__() 方法

(2).如果子类复写了 __init__() 方法,不会调用父类的 __init__() 方法, 但是不推荐这样使用

往后面直接添加 super().__init__() 方法就行

class Person(object):
    def __init__(self, name):
        self.name = name
        print('Perosn...')
 
 
class Student(Person):
    def __init__(self):  # 没有调用父类的__init__方法,就没有参数name传进来,会存在隐患,计算机会报错
        print('student...')
 
    def test(self):
        print(self.name)  # 没有参数name传进来,该语句无法执行
 
 
student = Student('zs')
student.test()
class Person(object):
    def __init__(self):
        print('Person...')
 
 
class Student(Person):
    def __init__(self):
        super().__init__()  # 调用父类的__init__()方法
        print('student...')
 
 
student = Student()
 
 
# Person...
# student...

三、派生属性 / 属性的覆盖

子类也可以添加自己新的属性,或者在自己这里定义这些属性(不会影响父类)

子类和父类有相同的属性时,将调用子类自己的属性。

class Person(object):
    num = 10
 
    def __init__(self, name):
        print('person...')
 
 
class Student(Person):
    num = 20
 
    def __init__(self, name, age):  # age是派生属性
        self.name = name
        self.age = age
        super().__init__(name)  # 调用父类的__init__()方法
        print('student...')
 
    def eat(self):
        print(super().num)  # 调用父类的num值
        print('xxxx')
 
 
student = Student('zs', 10)  # 创建对象时,调用自己的__init__()方法
student.eat()
print(student.num)
# person...
# student...
# 10
# xxxx
# 20

四,私有方法和私有属性在继承中的体现

父类中的私有方法和私有属性时不能被子类继承下来的

class Person(object):
    num = 10
    __num1 = 20  # 私有属性
 
    def __test1(self):  # 私有方法
        print('...test1...')
 
    def test2(self):
        print('Person test2')
 
 
class Student(Person):
    def test(self):
        Person.test2(self)
        print(Student.num)
        print('xxxx')
        # print(Person.__num1)  # 私有属性不能被继承下来
 
    def test3(self):
        print('test3')
        self.test()
        self.test2()
        # self.__test1()  # 私有方法能不能被继承下来
 
 
student = Student()
student.test()
student.test2()
student.test3()
# Person test2
# 10
# xxxx
# Person test2
# test3
# Person test2
# 10
# xxxx
# Person test2

五、抽象类

1,抽象类概述:

每个动物的吃,睡的状态都不一样,所以要在子类中复写这些方法,这样,父类中的方法就没用了,但不能把父类中的这些方法直接给删了,会报错,因此在这些方法中写个pass占位就不会报错了

如果子类继承父类的属性和方法,在子类中必须复写父类所有的属性和方法,否则会报错

抽象类中除了可以写抽象方法,还可以写普通方法

2,格式:

第一种:from abc import ABCMeta,abstractmethod

from abc import ABCMeta,abstractmethod

class 父类名(metaclass=ABCMeta):

    @abstractmethod

    def 方法(self):pass

from abc import ABCMeta, abstractmethod
 
 
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        pass
 
    @abstractmethod
    def sleep(self):
        pass
 
    def play(self):
        print('转悠...')
 
 
class Dog(Animal):
    def eat(self):
        print('吃狗粮...')
 
    def sleep(self):
        print('轻轻地睡觉...轻轻的看门')
 
 
dog = Dog()
dog.eat()
dog.sleep()

第二种:import abc

port abc

class 父类名(metaclass=abc.ABCMeta):

    @abc.abstractmethod

    def 方法名(self):pass

import abc
 
 
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def eat(self): pass
 
    @abc.abstractmethod
    def sleep(self): pass
 
    def play(self):
        print('转悠...')
 
 
class Dog(Animal):
    def eat(self):
        print('吃狗粮...')
 
    def sleep(self):
        print('轻轻的睡觉,轻轻地看门...')
 
 
dog = Dog()
dog.eat()
dog.sleep()

六、多继承

1,概念

一个子类可以继承多个父类,并且拥有多个父类所有的属性和方法

2,注意事项:

(1)  如果一个子类继承的多个父类中有相同的方法,子类该如何继承父类的方法呢?

使用   类名.mro()方法

          类名.__mro__()方法       来查看类的搜索路径

根据这个搜索路径来查找该继承谁的方法,一般情况是先写谁,就先调用谁

(2)  类的搜索路径的查找顺序:

  • 子类先于父类被检查
  • 多个父亲会根据它们在列表中的顺序被检查
  • 如果对下一个类存在两个合法的选择,选择第一个父类

Python 面向对象---继承

class A(object):
    num_1 = 10
 
    def test1(self):
        print('A test1')
 
    def test2(self):
        print('A test2')
class B(object):
    def test1(self):
        print('B test1')
 
    def test4(self):
        print('B test4')
class C(B, A):
    def test5(self):
        print('C test5')
 
    def test6(self):
        print('C test6')
c = C()
c.test1()  # B test1
print(C.mro())  # [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
print(C.__mro__)  # (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
c.test2()  # A test2
c.test4()  # B test4
c.test5()  # C test5
c.test6()  # C test6

七、继承原理 / 钻石原理

只有在Python3中才有mro()     __mro__()方法

来查找类的搜索路径

Python 面向对象---继承

八、多继承中的 super() 本质

super().方法名()

在每个类中调用test方法,沿着搜索路径往里退

class A(object):
    def test(self):
        print('A test')
 
 
class B(A):
    def test(self):
        super().test()
        print('B test')
 
 
class C(A):
    def test(self):
        super().test()
        print('C test')
 
 
class D(B, C):
    def test(self):
        super().test()
        print('D test')
 
 
d = D()
d.test()
print(D.mro())
print(D.__mro__)
# A test
# C test
# B test
# D test
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

 

Python 面向对象---继承