返回顶部
首页 > 资讯 > 后端开发 > Python >详析Python面向对象中的继承
  • 445
分享到

详析Python面向对象中的继承

2024-04-02 19:04:59 445人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录一单继承1.继承的基本语法格式如下2.查看类继承情况3.继承中的属性和方法4.初始化函数__init__()和super二多层继承三多重继承一 单继承 类继承作为python的三

一 单继承

类继承作为python的三大特性之一,在我们学习Python的时候是必不可少的。使用类继承,能够大大减少重复代码的编写。现来记录下,python中关于类继承的一些知识点。
类的继承有单继承,多层继承以及多重继承,先来看看单继承。

1. 继承的基本语法格式如下

#类继承语法格式,B类继承A类
class A():
    类属性
    类方法
    ...
class B(A):
    类属性
    类方法
    ...

单继承的话一般类A是没有继承其他派生类的,只继承了基类。因为在python新式类中,一个类会默认去继承基类object的,基类object是顶级类。

2. 查看类继承情况

class Father():
    #这是父类
    name1 = 'father_name'
    age1 = 'father_age'
    def father_method(self):
        print('我是父亲')

class Son(Father):
    #这是子类
    name2 = 'son_name'
    age2 = 'son_age'
    def son_method(self):
        print('我是孩子')

if __name__ == '__main__':
    A = Father()
    B = Son()
    #单继承
    print(B.__class__.__mro__)
    #或者Son.mro()
    print(Son.mro())

如上:我们定义了一个父类Father,一个子类Son,并且子类Son继承父类Father,它们都有自己的属性和方法。我们可以通过打印B.__ class__.__mro __ 或者Son.mro()来查看Son类的继承情况,如下:

>>>
(<class '__main__.Son'>, <class '__main__.Father'>, <class 'object'>)
[<class '__main__.Son'>, <class '__main__.Father'>, <class 'object'>]

可以看到,Son类确实继承了Father类,并且继承基类object。

3. 继承中的属性和方法

如果一个类继承了另外一个类,那么这个类是可以调用其继承类的属性和方法的(子类可以调用父类的属性和方法),如下

class Father():
    #这是父类
    name1 = 'father_name'
    age1 = 'father_age'
    def father_method(self):
        print('我是父亲')

class Son(Father):
    #这是子类
    name2 = 'son_name'
    age2 = 'son_age'
    def son_method(self):
        print('我是孩子')

    def fun1(self):
        #调用父类属性和方法
        print(self.age1, self.name1)
        self.father_method()

if __name__ == '__main__':
    A = Father()
    B = Son()
    #单继承
    # print(B.__class__.__mro__)
    B.fun1()

结果如下:

>>>
father_age father_name
我是父亲

当子类中的属性名方法名和父类中的属性名方法名同名时,在该子类中会覆盖父类的属性名和方法名(重写)。

class Father():
    #这是父类
    name1 = 'father_name'
    age1 = 'father_age'
    def father_method(self):
        print('我是父亲')

class Son(Father):
    #这是子类
    name1 = 'son_name'
    age1 = 'son_age'
    def son_method(self):
        print('我是孩子')

    def father_method(self):
        #和父类方法同名,将以子类方法为准
        print("与父类方法同名,但是我是子类")

    def son_fun1(self):
        #调用父类属性
        print("子类属性和父类属性同名,以子类为准:", self.name1, self.age1)


if __name__ == '__main__':
    A = Father()
    B = Son()
    #单继承
    # print(B.__class__.__mro__)
    B.father_method()
    B.son_fun1()

输出如下:

>>>
与父类方法同名,但是我是子类
子类属性和父类属性同名,以子类为准: son_name son_age

4. 初始化函数__init__()和 super

上面写的子类和父类都是不需要传参数的,而当我们需要给类传参数时,往往都是要初始化的,下面来看看子类继承父类时,参数初始化的几种情况。

子类无新增参数:

class Father():
    #父类
    def __init__(self, name='张三', age=23):
        self.name = name
        self.age = age

class Son(Father):
    #子类
    def son_fun1(self):
        print(self.name, self.age)

if __name__ == '__main__':
    B = Son()
    B.son_fun1()

输出:

>>>
张三 23

如上,在子类无新增参数时,无需进行__init__ 初始化,直接调用父类的对象属性即可。因为子类Son是继承自父类Father的,所以在调用时会首先去调父类的__init__ 进行初始化

子类有新增参数:

当子类有新增参数时,该怎么初始化呢?先来看看这个对不对

class Father():
    #父类
    def __init__(self, name='张三', age=23):
        self.name = name
        self.age = age

class Son(Father):
    #子类
    def __init__(self, height):
        self.height = height

    def son_fun1(self):
        print(self.height)
        print(self.name, self.age)

if __name__ == '__main__':
    B = Son(170)
    B.son_fun1()

输出:

>>>
AttributeError: 'Son' object has no attribute 'name'
170

上面子类Son新增了一个height参数,然后用__init__ 进行初始化。但是从输出结果可以看出,height参数是正常打印的,打印name和age参数时就报错:子类Son没有属性’name’,因为这个时候就不会去调用父类的__init__ 进行初始化,而是直接调用子类中的__init__ 进行初始化,这时,子类初始化就会覆盖掉父类的__init__ 初始化,从而报错。

正确的初始化有两种方法,如下:

#方法1
def __init__(self, 父类参数1, 父类参数2, ..., 子类参数1, 子类参数2, ...)
    父类名.__init__(self, 父类参数1, 父类参数2, ...)
    self.子类属性 = 子类属性

class Father():
    #父类
    def __init__(self, name='张三', age=23):
        self.name = name
        self.age = age

class Son(Father):
    #子类
    def __init__(self, name, age, height):
        #方法1
        Father.__init__(self, name, age)
        self.height = height

    def son_fun1(self):
        print(self.height)
        print(self.name, self.age)

if __name__ == '__main__':
    B = Son('李四', 24, 170)
    B.son_fun1()

>>>
175
李四 24

从结果可以看出,调用父类初始化后,结果就正常输出。这是在子类__init__初始化的时候,调用了Father.__ init __(self, name, age)对父类对象属性进行了初始化。

现在来看看另外一个初始化方法super()初始化,不过使用super()的时候要注意python的版本,因为python2和python3的使用是不同的,如下

#方法2
def __init__(self, 父类参数1, 父类参数2, ..., 子类参数1, 子类参数2, ...): 
    #python2的super初始化
    super(子类名, self).__init__(父类类参数1, 父类参数2, ...)
    self.子类属性 = 子类属性
    #python3的super初始化
    super().__init__(父类类参数1, 父类参数2, ...)
    self.子类属性 = 子类属性


class Father():
    #父类
    def __init__(self, name='张三', age=23):
        self.name = name
        self.age = age

class Son(Father):
    #子类
    def __init__(self, name, age, height):
        #方法2
        #python2的super初始化
        super(Son, self).__init__(name, age)
        self.height = height
        #python3的super初始化
        # super().__init__(name, age)
        #或者 super(Son, self).__init__(name, age)
        
    def son_fun1(self):
        print(self.height)
        print(self.name, self.age)

if __name__ == '__main__':
    B = Son('李四', 24, 175)
    B.son_fun1()

结果:

>>>
175
李四 24

上面使用的是super(Son, self).__ init __ (name, age) 来对父类对象属性进行初始化。不过这是要区分python版本的,在python3中使用super(Son, self).__ init__(name, age)或者super().__ init__(name, age)都是可以的,但是在python2的版本中,要使用super(Son, self).__ init__(name, age)来进行初始化,而且父类必须继承object,否则就会报错。

二 多层继承

上面的记录的是单继承,现在来看看多层继承。多层继承:子类继承自多个父类,父类只继承自object顶级类。

class Father():
    def __init__(self):
        print("enter father")
        print("leave father")

    def fun(self):
        print("这是father")

class Mother():
    def __init__(self):
        print("enter mother")
        print("leave mother")

    def fun(self):
        print("这是mather")

class Son(Father, Mother):
    def __init__(self):
        print("enter son")
        super().__init__()
        print("leave son")

if __name__ == '__main__':
    B = Son()
    B.fun()
    print(Son.mro())

输出:

>>>
enter son
enter father
leave father
leave son
这是father

继承关系:

[<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>]

这里有两个父类Father,Mother,一个子类Son,子类Son继承了类Father和Mother,继承顺序是Father在前,Mother在后。从上面输出结果来看,子类初始化过程是先进入子类Son的 __ init __方法,其次调用super(). __init __()进行父类对象属性初始化,最后初始化完成。
从结果可以知道上面super初始化调用的是父类Father的 __ init __方法。
。也可以看出,类Father和类Mother都有一个fun方法(同名),但在子类调用时调的是父类father的fun方法。这是为什么呢?

这里就涉及到super的继承机制,即super会根据MRO机制,从左到右依次调用父类的属性和方法, 当父类中有同属性名,同方法名时,以靠左的那个父类为准。

下面我们把Father和Mother位置换一下,如下:

class Father():
    def __init__(self):
        print("enter father")
        print("leave father")

    def fun(self):
        print("这是father")

class Mother():
    def __init__(self):
        print("enter mother")
        print("leave mother")

    def fun(self):
        print("这是mather")

class Son(Mother, Father):#这里变动,变换Father和Mother的位置
    def __init__(self):
        print("enter son")
        super().__init__()
        print("leave son")

if __name__ == '__main__':
    B = Son()
    B.fun()
    print(Son.mro())

结果:

>>>
enter son
enter mother
leave mother
leave son
这是mather
[<class '__main__.Son'>, <class '__main__.Mother'>, <class '__main__.Father'>, <class 'object'>]

继承关系:

>>>
[<class '__main__.Son'>, <class '__main__.Mother'>, <class '__main__.Father'>, <class 'object'>]

可以看出,当Mother在前时,调用的就是类Mather的初始化方法和fun方法。所以在多层继承时,一定要注意父类的位置顺序。

三 多重继承

其实super的产生就是用来解决多重继承问题的,什么是多重继承呢?即,子类继承多个父类,而父类又继承自其它相同的类,这种又被称为菱形继承或者砖石继承,

如下:

     A
   /   \
  /     \
 B       C
  \     /
   \   /
     D

先来看看如下的一个菱形继承:

class A():
    def __init__(self):
        print("enter A")
        print("leave A")

class B(A):
    def __init__(self):
        print("enter B")
        # super().__init__()
        A.__init__(self)
        print("leave B")

class C(A):
    def __init__(self):
        print("enter C")
        # super().__init__()
        A.__init__(self)
        print("leave C")

class D(B, C):
    def __init__(self):
        print("enter D")
        B.__init__(self)
        C.__init__(self)
        # super().__init__()
        print("leave D")

if __name__ == '__main__':
    d = D()

输出结果:

>>>
enter D
enter B
enter A
leave A
leave B
enter C
enter A
leave A
leave C
leave D
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

上面用的是父类名. __ init__ () 来进行子类初始化的,但是从结果来看,类A的初始化方法是被执行了两次的,一次是类B的调用,一次是类C的调用。也可以看出子类D的初始化 __ init __ 调用了B.__ init __() 和C. __init __() 。现在D类继承的父类只有B和C,但是当代码比较复杂,继承的类比较多时,就得的一个一个写,如果类B和类C也是继承自多个类,那它们的初始化方法也得重新写,这样就比较繁琐,也容易出错。

下面来使用super初始化父类看看:

class A():
    def __init__(self):
        print("enter A")
        print("leave A")

class B(A):
    def __init__(self):
        print("enter B")
        super().__init__()
        print("leave B")

class C(A):
    def __init__(self):
        print("enter C")
        super().__init__()
        print("leave C")

class D(B, C):
    def __init__(self):
        print("enter D")
        super().__init__()
        print("leave D")

if __name__ == '__main__':
    d = D()
    print(D.mro())

输出结果:

enter D
enter B
enter C
enter A
leave A
leave C
leave B
leave D
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

可以看到输出结果是不一样的,类A的初始化只执行了一次,而且当D类有新增父类时,初始化方法也不用动,从而避免重写初始化方法出错,代码也变得整洁。
这里还是和super的继承机制有关,上面说过当子类继承自多个父类时,super会根据MRO机制,从左到右依次调用父类的属性和方法,而且使用super初始化父类时,会一次性初始化所有的父类,所以上面的类A初始化方法不会被调用两次。

所以在类的多重继承中,一般建议使用super来初始化父类对象属性。

到此这篇关于详析Python面向对象中的继承的文章就介绍到这了,更多相关Python面向对象继承内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 详析Python面向对象中的继承

本文链接: https://lsjlt.com/news/141552.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 详析Python面向对象中的继承
    目录一单继承1.继承的基本语法格式如下2.查看类继承情况3.继承中的属性和方法4.初始化函数__init__()和super二多层继承三多重继承一 单继承 类继承作为python的三...
    99+
    2024-04-02
  • Python面向对象——继承
    #coding:utf-8 """ 术语: 1、在python3中,自定义创建的类都默认继承了python类中名为object的类 2、object类提供的方法,是双下划线开头的,是为了提供给python内部使用 3、被继承的类叫做超类,...
    99+
    2023-01-31
    面向对象 Python
  • python 面向对象之继承
    文章目录 前言继承的概念单继承多继承子类重写父类的同名方法和属性子类调用父类同名的方法和属性多层继承私有权限 前言 前面我们已经学习了 python 面向对象的类和对象,那么今天我将为大...
    99+
    2023-09-01
    python 开发语言
  • 详解Java面向对象中的继承
    继承的概念 继承是面向对象编程中的一个概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。子类在继承父类的同时也可以添加自己的属性和方法,从而实现代码的...
    99+
    2023-05-19
    Java 面向对象 Java 继承
  • python面向对象之类的继承详解
    目录一、概述 二、类的继承2.1 继承的定义2.2 构造函数的继承 2.3 子类对父类方法的重写三、类继承的事例一、概述  面向对象编程 (OOP) 语言的一个主要功能就是“继承”。...
    99+
    2024-04-02
  • python 面向对象之类的继承
    python中什么是继承:新类不必从头编写新类从现有的类继承,就自动拥有了现有类的所有功能新类只需要编写现有类缺少的新功能继承的好处:复用已有代码自动拥有了现有类的所有功能只需要编写缺少的新功能继承的特点:子类和父类是is关系python继...
    99+
    2023-01-30
    面向对象 python
  • Python中关于面向对象中继承的详细讲解
    目录1.继承2.单继承3.多继承4.子类重写父类的同名属性和方法5.子类调用父类同名属性和方法6.多层继承7.调用父类方法super()8.案例1.继承 在程序中,继承描述的是多个类...
    99+
    2024-04-02
  • python 面向对象之继承顺序
    先来看一个经典类class A:     def __init__(self):         p...
    99+
    2023-01-30
    面向对象 顺序 python
  • Java全面分析面向对象之继承
    目录继承什么是继承呢?子类访问父类的成员变量子类访问父类非同名成员变量子类访问父类同名成员变量子类访问父类的成员方法子类访问父类的非同名方法子类访问父类的同名方法super关键字su...
    99+
    2024-04-02
  • JavaScript面向对象中继承的概念
    本篇内容介绍了“JavaScript面向对象中继承的概念”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、...
    99+
    2024-04-02
  • 详解Java面向对象中的继承与多态
    详解Java面向对象中的继承与多态?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java 继承与多态的深入理解1、  什么是继承,继承的特点?子类继承父类的特征和...
    99+
    2023-05-31
    java 面向对象 ava
  • Python面向对象编程之类的继承
    目录1、对继承的理解2、类继承的构建3、Python中最基础的类4、ython类的重载4.1 属性重载4.2 方法重载5、类的多继承1、对继承的理解 继承(Inheritance) ...
    99+
    2024-04-02
  • Java面向对象之继承的概念详解
    目录1. 继承1.1 继承的实现1.2 继承的好处和弊端1.3. Java中继承的特点2. 继承中的成员访问特点2.1 继承中变量的访问特点2.2 super2.3 方法重写2.4 ...
    99+
    2023-05-18
    Java 继承 Java 面向对象
  • JAVA面向对象中如何继承super
    小编今天带大家了解JAVA面向对象中如何继承super,文中知识点介绍的非常详细。觉得有帮助的朋友可以跟着小编一起浏览文章的内容,希望能够帮助更多想解决这个问题的朋友找到问题的答案,下面跟着小编一起深入学习“JAVA面向对象中如何继承sup...
    99+
    2023-06-28
  • Python基础面向对象之继承与派生详解
    目录一、面向对象三大特征之继承1、继承的概念2、继承的本质3、继承的实操4、继承后名字查找的顺序5、经典类与新式类二、派生1、派生的概念2、派生的方法一、面向对象三大特征之继承 py...
    99+
    2024-04-02
  • python 面向对象之继承实例讲解
    面向对象编程语言具有封装、继承、多态三个基本特征,本文就继承举例详谈比如说学校主要有3大角色:学校,讲师,学员学校可以注册学员,统计有多少学员老师负责讲课学生听课,提问,学习,交学费先定义4个类:class School(obje...
    99+
    2023-01-30
    面向对象 实例 python
  • JAVA面向对象之继承 super入门解析
    目录1 继承1.1概念1.2 特点1.3 练习:继承入门案例2 super3 继承的用法3.1 练习:super之继承中成员变量使用3.2 练习:super之继承中构造方法的使用4 ...
    99+
    2024-04-02
  • 深入浅析java中面向对象的继承和多态
    深入浅析java中面向对象的继承和多态?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。继承和多态一.this super关键字this: 可以在构造器中的第一代码中...
    99+
    2023-05-31
    java 继承 多态
  • 【Java基础篇 | 面向对象】—— 继承
    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习Java...
    99+
    2023-10-11
    java 开发语言 面向对象
  • 面向对象封装、继承、多态
    一、面向对象封装   01. 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象,然后 让对象调用方法 对象方法的细节 都被 封装...
    99+
    2023-01-31
    面向对象 多态
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作