1. 程式人生 > >python之子類繼承父類時進行初始化的一些問題

python之子類繼承父類時進行初始化的一些問題

直接看程式碼:

class Person:
    def __init__(self):
        self.name = "jack"
class Student(Person):
    def __init__(self):
        self.school = "一中"
stu = Student()
print("學生的姓名是:",stu.name)

此時,程式是不能正常執行的,執行之後報錯:

這是為什麼呢?

__init__相當於是python類的構造方法,在類進行例項化時被呼叫,當子類和父類中都存在構造方法時,子類中需要顯示呼叫父類的構造方法 。需要注意的是python中構造方法是不能進行過載的,當有多個構造方法存在時,會預設呼叫最後一個構造方法。修改後的程式碼如下:

class Person:
    def __init__(self):
        self.name = "jack"
class Student(Person):
    def __init__(self):
        super(Student, self).__init__()
        self.school = "一中"
stu = Student()
print("學生的姓名是:",stu.name)

此時的結果就是正常的。

super(Student, self).__init__():其中super關鍵字表示父類,Student是本類的名稱,self指代本類自己。

在python中如何設定私有屬性和方法?

將屬性和方法前面加上__(雙下劃線)。加上了私有的屬性和方法不能在類外進行訪問,同時,子類繼承父類的屬性和方法時,在子類中也不能夠訪問父類的私有屬性和方法。

舉個例子:

class Person:
    def __init__(self):
        self.__name = "jack"
    def __test(self):
        print("這是父類的私有方法")
class Student(Person):
    def __init__(self):
        super(Student, self).__init__()
        super().__test()
        self.school = "一中"
stu = Student()

以上程式碼會報錯:

要想訪問到父類的私有屬性和方法,需這樣做:

class Person:
    def __init__(self):
        self.__name = "jack"
        self.age = 12
    def __test(self):
        print("這是父類的私有方法")
    def test(self):
        print("這是父類的公有方法")
class Student(Person):
    def __init__(self):
        super(Student, self).__init__()
        self.school = "一中"
    def printStudent(self):
        #子類自己繼承了父類的公有屬性,直接訪問即可
        print("在子類中使用父類的共有屬性:",self.age)
        #super()代表父類,可以訪問父類的公有方法
        #當然如若子類沒有重寫父類的方法,也可以使用self.test()來呼叫
        #super和self區別:super是指代父類,self指代該類本身
        super().test()
        #對於父類的私有屬性和方法,需要通過_父類名__屬性或方法名來訪問
        #super()._Person__test()
        self._Person__test()
stu = Student()
print("學生的姓名是:",stu._Person__name)
print("學生的年齡是:",stu.age)
stu._Person__test()
stu.printStudent()

輸出:

需要明確的是python中並沒有真正意義上的私有修飾符,從以上的程式碼也可以看出。Python在執行時會將__屬性或方法轉換成:_類名__屬性或方法。通過這種方式就可以訪問到類私有屬性或方法。還有一種方式就是通過在類內部再定義一個公有方法,來呼叫私有的屬性或方法,在子類進行呼叫時呼叫這個公有的方法即可,這也就是面向物件中封裝的作用之一,在接下來會結合進行介紹。

那麼假設父類的構造器帶有引數,那麼在子類中應該如何進行初始化呢?

子類要在初始化的時候顯示呼叫父類的有參構造,並且傳入相應的引數,具體程式碼如下:

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def __test(self):
        print("這是父類的私有方法")
    def test(self):
        self.__test()
        print("這是父類的公有方法")
    def setAge(self,age):
        self.__age = age
    def getAge(self):
        return self.__age
class Student(Person):
    def __init__(self,school,name,age):
        super(Student, self).__init__(name=name,age=age)
        self.school = school
    def stuTest(self):
        super().test()
        print("所在學校為:",self.school)
stu = Student("一中","tom",12)
stu.stuTest()
print("學生的姓名是:",stu.name)
print("學生的年齡是:",stu.getAge())

輸出:

補充:

假設父類中沒有顯示的定義建構函式,那麼在子類中就不用顯示的定義父類的建構函式。

class Person:
    def test(self):
        print("什麼都沒有")
class Student:
    def __init__(self,name):
        self.name = name
stu = Student("tom")
print("姓名是:",stu.name)

輸出: