Python中类的继承方法

本文详细介绍了Python中类的继承机制,包括构造函数的作用、不同继承方式的比较,以及新式类与经典类的区别。重点讲解了如何正确使用`__init__`、`super()`以及`mro`元组来实现高效继承并避免资源浪费。
摘要由CSDN通过智能技术生成

Python中类与类之间可以继承,继承的叫父类或超类,新创建的叫子类。通过继承,子类可以使用父类的属性,这样可以有效减少代码的冗余度,提高代码重用性。

谈到类的继承,首先要了解构造函数或构造方法。

构造函数或构造方法

在Python中,一个类,不管是否写了构造函数,它都是具有构造函数的一个类,它可以拥有多个构造函数,但建议一个类只有一个构造函数。

当一个对象被创建后,会立即调用构造函数。例如,我们创建了example类如下:

class example_a(object):
    def add(self,a,b):
        return a + b

test_a = example_a()
print(test_a.add(10,20)) ## 30
#####################################
class example_b(object):
    def __init__(self,a,b):
        self.a = a
        self.b = b
    def add(self):
        return self.a + self.b

test_b = example_b(10,20)
print(test_b.add()) ## 30

在类example_a中,我们没有给出构造函数,因为class类是默认有构造函数的,只是没有显示出。class类默认的构造函数是不带参数的,因此在实例化的时候,test_a = example_a()不带参数。

在类example_b中,我们定义了构造函数def __init__(self,a,b) ,test_b=example_b(10,20)就是对example_b类进行实例化。

了解了构造函数后,我们再来看类的继承。

类的继承

我们首先定义一个父类和2个子类。

class Father(object):
    def __init__(self):
        self.name = 'XiaoMing'
        print ( "Name : %s" %( self.name) )
    def get_name(self):
        return "Name : " + self.name

class Son_A(Father):
    def get_name(self):
        return 'Name : '+self.name

class Son_B(Father):
    def __init__(self):
        self.age=  18
        print ( "Age is " + str(self.age) )
    def get_age(self):
        return 'Age is ' + str(self.age)

这里,子类 Son_A 和 Son_B 都继承了父类,但子类 Son_A 没有重写 __init__()函数,因此在实例化子类 Son_A 时,会自动调用父类定义的 __init__()函数;而子类 Son_B 重写了__init__()函数,因此在实例化 Son_B 子类,就不会调用父类已经定义的__init__()函数。

这里,需要注意重写与C++里面的重载有区别,C++中允许在同一范围中声明几个功能类似的同名函数,函数根据形参个数、类型或顺序的不一样,调用不同的方法。但在Python中,不允许有重名的函数,如果有重名的函数,后出现的函数会将之前的函数覆盖掉,因此在python中几乎没有重载。

Son_B 子类重写了__init__()函数,但却没有任何关于父类的特性。因此,在很多情况下,我们必须要调用父类的构造方法来确保基本的初始化。我们完全可以将父类的构造函数复制到子类中去,然后对子类进行重写,但这就变得十分繁琐,失去了继承的意义。这里我们介绍三种方法对父类进行继承。

第一种

在子类的__init__()函数中,添加 父类名称.__init__(self,参数1,参数2,...),如下代码:

class Father(object):
    def __init__(self):
        self.name = 'XiaoMing'
        print ( "Name : %s" %( self.name) )
    def get_name(self):
        return "Name : " + self.name

class Son_C(Father):
    def __init__(self):
        Father.__init__(self)
        self.age=  18
        print ( "Age is " + str(self.age) )
    def get_age(self):
        return 'Age is ' + str(self.age)

第二种

在子类的__init__()函数中,添加 super().__init__(参数1,参数2,...),代码如下:

class Father(object):
    def __init__(self):
        self.name = 'XiaoMing'
        print ( "Name : %s" %( self.name) )
    def get_name(self):
        return "Name : " + self.name

class Son_C(Father):
    def __init__(self):
        super().__init__()
        self.age=  18
        print ( "Age is " + str(self.age) )
    def get_age(self):
        return 'Age is ' + str(self.age)

第三种

在子类的__init__()函数中,添加 super(Son_C,self).__init__(参数1,参数2,...),代码如下:

class Father(object):
    def __init__(self):
        self.name = 'XiaoMing'
        print ( "Name : %s" %( self.name) )
    def get_name(self):
        return "Name : " + self.name

class Son_C(Father):
    def __init__(self):
        super(Son_C,self).__init__()
        self.age=  18
        print ( "Age is " + str(self.age) )
    def get_age(self):
        return 'Age is ' + str(self.age)

注意,在第一种继承方法中,如果一个父类有多个子类,子类(相当于父类)中又有多个子类,即一个子类D继承了2个父类B和C,两个父类B和C又继承了父类A,且每个类都有__init__()方法,那么如果使用第一种方法对类进行继承,可能会出现父类A被重复执行多次,因为子类D会调用父类B和C,而父类B和C又分别调用了父类A,这样父类A就会被重复执行2次,造成了资源的浪费。所以,一般建议使用super方法。

当 super 去调用父类的方法时,这里需要注意调用的顺序问题,super 调用父类的顺序,是由 python 解释器里面的C3算法决定的(多继承查找规则),具体可以通过下列代码查看:

print(Son_C.__mro__)
##输出结果##
(<class '__main__.Son_C'>, <class '__main__.Father'>, <class 'object'>)

mro元组的先后顺序就是super调用父类时的顺序。例如,当在Son_C类中执行super时,根据mro元组顺序,super会调用<class '__main__.Son_C'>的下一个,即<class '__main__.Father'>,如果在<class '__main__.Father'>中还有super,那么会根据mro元组的顺序,super会调用<class '__main__.Father'>的下一个,以此类推。

最后

新式类与经典类的区别:

  • 继承了object的类以及该类的子类,都是新式类。

    在Python3中如果一个类没有继承任何类,则默认继承object类。因此python3中都是新式类

  • 没有继承object的类以及该类的子类,都是经典类。

    在Python2中如果一个类没有继承任何类,不会继承object类。因此,只有Python2中有经典类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值