1. 程式人生 > >面向對象之繼承

面向對象之繼承

def 菱形 style lose 點語法 name sub 方式 簡單的

一.繼承基礎

1.什麽是繼承?

繼承指的是一種關系,它必須存在兩個對象,才會發生繼承這件事。在程序中,繼承指的是類與類之間的關系。被繼承的稱為父,繼承的稱為子。

2.為什麽要使用繼承?

在程序中,通過繼承可以直接使用父類已有的代碼,從而簡化代碼。

3.如何使用繼承?

語法:在子類中,類名後面加括號,括號裏寫上父類的名稱即可,可以是多個,用逗號分隔開。

子類可以使用父類中的屬性,也可以使用父類中的函數。

技術分享圖片
# class Father:
#     pass
#
#
# class GanDie:
#     pass
#
# # 在子類中 類名後面加上括號,些上父類的名稱即可,
# # 在python中一個子類可以有多個父類,多個父類在括號中用逗號隔開,,這一點在其他語言中是不支持的
# class Son(Father,GanDie): # pass class Parent: year = 2018 def coding(self): print("正在編程........") class Sub(Parent): pass print(Parent.year) print(Sub.year) # Sub.coding() s = Sub() print(s.year) # 子類可以使用父類中的屬性 s.coding() # 子類也可以父類中的函數
繼承的使用

子類繼承父類之後會出現一個問題,就是子類可能會繼承到一些不應該有的屬性,這就需要用到抽象的概念。

抽象指的是抽取多個類中相同的部分形成另一個類。這樣就可以避免繼承到一些不應該有的內容,在抽取的過程中,也可能會產生一些跟業務需求無關的類,但是並不影響。

技術分享圖片
class Person:
    def __init__(self ,name ,age ,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        print("正在吃飯....")

    def study(self):
        print("正在學習....")

class Teacher(Person): def teaching(self): print("老師正在上課......") t1 = Teacher("blex" ,30 ,"woman") t1.eat() t1.study() class Student(Person): pass stu1 = Student("張三" ,20 ,"man") stu1.eat() stu1.study()
抽象

二.派生與覆蓋

1.什麽是派生?

派生指的是子類繼承某個父類,並且子類擁有自己獨特的屬性或者技能。只要子類中出現了任何新的內容,它就是一個派生類。

技術分享圖片
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def sayHI(self):
        print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex))


# Test不能稱為派生類 , 因為沒與任何獨特的內容與父類完全一致
class Test(Person):
    pass

# 派生類屬於子類嗎?   派生類一定是某個子類
# Student類就成為 Person類的派生類


class Student(Person):
    def __init__(self,name,age,sex,number):
        self.name = name
        self.age = age
        self.sex = sex
        self.number = number

    # 上課
    def up_class(self):
        print("%s 正在上課.....")
派生

2.什麽是覆蓋?

在子類中,如果存在與父類相同的屬性名稱時,優先使用子類中的屬性,這種行為稱之為覆蓋。

三.子類訪問父類的方法

簡單的來說有兩種方法:

1.指名道姓的訪問(父類名點語法)

2.用super()函數訪問(super()點語法)。該函數一定是用在存在繼承關系的子類中的。在python2中用法:super(子類名,self)點語法。

技術分享圖片
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        print(self)

    def sayHI(self):
        print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex))


class Student(Person):
    def __init__(self,name,age,sex,number):
        # self.name = name
        # self.age = age
        # self.sex = sex
        #上述代碼與父類中完全相同
        Person.__init__(self,name,age,sex)
        self.number = number
    # 上課
    def up_class(self):
        print("%s 正在上課.....")

    def sayHI(self):
        # print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex))
        # 訪問父類中的方法來簡化代碼
        # 指名道姓
        Person.sayHI(self)
        
        print("學號:",self.number)

stu1 = Student("阿三",20,"woman","9527")
# print(stu1)
# print(stu1.name,stu1.age,stu1.sex)
stu1.sayHI()
方法一 技術分享圖片
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        print(self)

    def sayHI(self):
        print("hello 我是%s 今年%s歲 性別:%s" % (self.name,self.age,self.sex))

class Student(Person):
    def __init__(self,name,age,sex,number):
        # self.name = name
        # self.age = age
        # self.sex = sex
        # 子類中重用父類種方法的方式2
        # super() # 表示創建一個特殊的對象 用於調用父類的方法
        # super().__init__(name,age,sex)
        # 了解:在python2中 super的使用方式有所不同 需要傳入當前類,當前對象
        super(Student,self).__init__(name,age,sex)
        self.number = number

    # 上課
    def up_class(self):
        print("%s 正在上課.....")

stu1 = Student("阿三",20,"woman","9527")
print(stu1)
print(stu1.name,stu1.age,stu1.sex)
方法二

四.繼承的屬性查找順序

查找順序:對象---》類---》父類---》父類的父類......

優先查找對象,如果不存在,則找類,如果類中不存在,則會沿著繼承關系一直找到最頂層的父類。方法的查找順序也是一樣。

技術分享圖片
class S:
    age = 17

    def f1(self):
        print("S f1")

class A(S):
    # age = 18
    # def f1(self):
    #     print("A f1")
    pass
class B(A):
    # age = 19
    # def f1(self):
    #     print("B f1")
    pass
b = B()
# b.age = 20

print(b.age)

print(b.__dict__)
print(B.__dict__)
print(A.__dict__)

# 對象 -> 類 ->父類 ->父類的父類.....
# 優先找對象 如歌對象沒有 則找類,如果類沒有,會沿著繼承關系一直找到最頂層的父類
# 無論是屬性還是方法 查找順序是一樣的
b2 = B()
b2.f1()
基本查找順序

如果繼承關系為菱形結構,那麽屬性的查找方式有兩種,分別是:深度優先和廣度優先

技術分享圖片

技術分享圖片

技術分享圖片
# class E:
#     a = 5
#
# class A(E):
#     a = 4
#     pass
#
# class B:
#     a = 3
#     pass
#
# class C:
#     a = 2
#     pass
#
# class D(A,B,C):
#     # a = 1
#     pass
#
# d1 = D()
# # d1.a = 10
# print(d1.a)

# 1.按照繼承的順序 先繼承誰就先找誰


class S:
    a = 100

class A(S):
    # a = 1
    pass
class B(S):
    # a = 2
    pass
class C(S):
    # a = 3
    pass
class D(A):
    # a = 4
    pass
class E(B):
    # a = 5
    pass
class F(C):
    # a = 6
    pass
class G(D,E,F):
    pass


g1 = G()
print(g1.a)
print(G.mro())

"""
s
a,b,c
d,e,f
g
"""
菱形繼承的屬性查找

五.經典類與新式類

新式類:所有直接或間接繼承object的類都是新式類。object稱之為根類,即所有的類都源自於object類。(創建對象時,需要申請內存空間,創建新的名稱空間,將對象的屬性放入名稱空間,這一些了復雜的基礎操作,都有object來完成。簡單地說:object提供了一些常用的基礎操作。)

在python3中默認所有類都是新式類,在python2中默認是經典類(不會自動繼承object)。

__bases__用於查看父類,mro()方法是一個列表,存放的是屬性的查找順序。

技術分享圖片
"super訪問父類內容時 按照mro列表屬性查找"

class S:
    def f1(self):
        print("s f1")

class A(S):
    pass

class B(S):
    def f1(self):
        print("b f1")
    pass

class C(A,B):
    def f2(self):
        print("c f2")
        super().f1()


print(C.mro())
c1 = C()
c1.f2()

class S:
    pass
class Student(S):
    pass

# __bases__用於查看父類
print(Student.__bases__)

# 顯示屬性的查找順序列表,屬性查找屬性就是按照該列表來查找的
print(Student.mro())
View Code

面向對象之繼承