Python 构造函数

构造函数

        构造函数就是为了让我们再实例化对象的时候能够实现个性化定制。

1. __init__()

        大家可以理解为在实例化对象之前就会自动执行的函数,如:

class A():   #定义类A
    def __init__(self,x,y): #创建构造方法__init__()
      #等号左边是绑定到实例化对象里面的属性值,等号右边是传进来的参数
        self.x = x
        self.y = y
    def add(self):          #返回x,y的和
        return self.x + self.y
    
    def mul(self):          #返回x,y的积
        return self.x * self.y 

a = A(2,3)
a.add()
# 5
a.mul()
# 6
a.__dict__ #查看实例对象a中的数据
# {'x': 2, 'y': 3}
b = A(4,5)
b.add()
# 9
b.mul()
# 20
b.__dict__ #查看实例对象b中的数据
# {'x': 4, 'y': 5}

        上述代码中,我们并没有调用__init__()方法,然而我们却得到了传进来的值,说明在我们调用方法之前就已经运行__init__()方法了。

2. 重写

        有构造函数的类的继承:

class A():   #定义类A
    def __init__(self,x,y): #创建构造方法__init__()
      #等号左边是绑定到实例化对象里面的属性值,等号右边是传进来的参数
        self.x = x
        self.y = y
    def add(self):          #返回x,y的和
        return self.x + self.y
    
    def mul(self):          #返回x,y的积
        return self.x * self.y 



class B(A):   #定义类B,并且继承类A
    def __init__(self,x,y,z):
        A.__init__(self,x,y) #继承父类的方法
        self.z = z
    def add(self):
        return A.add(self) + self.z
    
    def mul(self):
        return A.add(self) * self.z

b = B(1,2,3)
b.add()
# 6
b.mul()
# 9

        通过上述代码可以看出我们直接通过 父类类名.方法名 重新父类的方法是可以达到效果的,不过这种方法会导致钻石继承。

3. 钻石继承

        所谓钻石继承是指,两个类同时继承了一个父类,并且这两个类又同时被一个子类继承。

如下图,B1、B2 同时继承类A,而B1、B2 又同时被被C继承。

        可是钻石继承会导致什么后果呢,我们举个例子:

class Grandmother:    #定义Grandmother类
    def __init__(self):
        print("我是奶奶,我进动物园了,我要买票!")

class Father(Grandmother):  #定义Father类,并且继承类Grandmother
    def __init__(self):
        Grandmother.__init__(self)
        print("我是爸爸,我进动物园了,我要买票!")

class Uncle(Grandmother):  #定义Uncle类,并且继承类Grandmother
    def __init__(self):
        Grandmother.__init__(self)
        print("我是叔叔,我进动物园了,我要买票!")

class Me(Father,Uncle): #定义Me类,并且继承类Father和Uncle
    def __init__(self):
        Father.__init__(self)
        Uncle.__init__(self)
        print("我是小明,我进动物园了,我要买票!")

m = Me()

 运行结果:

我是奶奶,我进动物园了,我要买票!
我是爸爸,我进动物园了,我要买票!
我是奶奶,我进动物园了,我要买票!
我是叔叔,我进动物园了,我要买票!
我是小明,我进动物园了,我要买票!

         因为Father和Uncle同时继承了Grandmother类,导致Grandmother类中的__init__()在整个程序中被访问了两次,对于变成来说变得不严谨了,就相当于因为奶奶同时使爸爸和叔叔的妈妈,所以奶奶要买两张票才能进动物园一样。

        有什么可以钻石继承的问题呢,这里就使用到了super()函数。

4. super()  

        super()可以在父类中搜索指定的方法,并自动绑定好self参数,避免重复调用的问题。

class Grandmother:
    def __init__(self):
        print("我是奶奶,我进动物园了,我要买票!")

class Father(Grandmother):
    def __init__(self):
       super().__init__() #使用super函数
       print("我是爸爸,我进动物园了,我要买票!")

class Uncle(Grandmother):
    def __init__(self):
        super().__init__()   #使用super函数
        print("我是叔叔,我进动物园了,我要买票!")

class Me(Father,Uncle):
    def __init__(self):
       super().__init__()   #使用super函数
       print("我是小明,我进动物园了,我要买票!")

m = M()

运行结果:

        这里奶奶只买了一次票,说明使用super可以避免重复调用的问题。

我是奶奶,我进动物园了,我要买票!
我是叔叔,我进动物园了,我要买票!
我是爸爸,我进动物园了,我要买票!
我是小明,我进动物园了,我要买票!

5.MRO顺序

      prthon类是支持(多)继承的,一个类的方法和属性可能定义在当前类,也可能定义在基类。针对这种情况,当调用类方法或类属性时,就需要对当前类以及它的基类进行搜索,以确定方法或属性的位置,而搜索的顺序就称为方法解析顺序。

        对于初学者来说,MRO顺序比较难理解,这里我们可以使用两种方法来查找MRO。

1. 通过mro()方法

Me.mro()

[<class ‘__main__.Me’>, <class ‘__main__.Father’>, <class ‘__main__.Uncle’>, <class ‘__main__.Grandmother’>, <class ‘object’>]

        根据运行结果我们可以清晰地看出搜索顺序,这里注意,对于<class ‘object’>,我们在上述代码中并没有定义,可是通过mro方法却能检测出来,这是因为object使所有类的基类,无论什么情况,都会自动调用的。

2. 通过mro属性 __mro__

Me.__mro__

(<class ‘__main__.Me’>, <class ‘__main__.Father’>, <class ‘__main__.Uncle’>, <class ‘__main__.Grandmother’>, <class ‘object’>)

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年11月14日
下一篇 2023年11月14日

相关推荐