Python教程:類與類之間的關係

一.類與類之間的依賴關係python

大千世界, 萬物之間皆有規則和規律,咱們的類和對象是對大千世界中的全部事物進行歸類,那事物之間存在着相對應的關係,類與類之間也一樣如此,在面向對象的世界中. 類與類中存在如下關係:編程

  1. 依賴關係app

  2. 關聯關係編程語言

  3. 組合關係學習

  4. 聚合關係設計

  5. 繼承關係code

  6. 實現關係對象

因爲python是一門弱類型編程語言,而且全部的對象之間其實都是多態的關係,也就是說,全部的東西均可以當作對象來使用, 因此咱們在寫代碼的時候很容易造成以上關係.首先,咱們先看第一種, 也是這些關係中緊密程度最低的一個, 依賴關係.繼承

首先, 咱們設計一個場景,仍是最初的那個例子,要把大象裝冰箱,注意,在這個場景中, 實際上是存在了兩種事物的, 一個是大象, 大象負責整個事件的掌控者, 還有一個是冰箱, 冰箱負責被大象操縱.事件

首先, 寫出兩個類, 一個是大象類, 一個是冰箱類

class Elphant:
    def __init__(self, name):
        self.name = name
    def open(self):
        '''
        開門
        :return :return:
        '''
        pass
    def close(self):
        '''
        關門
        :return :return:
        '''
        pass
class Refrigerator:
  
    def open_door(self):
        print("冰箱門被打開了")
  
    def close_door(self):
        print("冰箱門被關上了")

冰箱的功能很是簡單, 只要會開門關門就好了. 可是大象就沒那麼簡單了,想一想,大象開門和關門的時候是否是要先找個冰箱啊, 而後呢? 打開冰箱門,是否是打開剛纔找到的那個冰箱門, 而後裝本身,最後呢? 關冰箱門, 注意, 關的是剛纔那個冰箱吧. 也就是說, 開門和關門用的是一個冰箱,而且大象有更換冰箱的權利, 想進哪一個冰箱就進哪一個冰箱. 這時, 大象類和冰箱類的關係並無那麼的緊密,由於大象能夠指定任何一個冰箱. 接下來,咱們把代碼完善一下.

class Elphant:
    def __init__(self, name):
        self.name = name
    def open(self, ref):
        print("大象要開門了. 默唸三聲. 開!")
        # 由外界傳遞進來一個冰箱, 讓冰箱開門, 這時大象不用揹着冰箱處處跑.
        # 類與類之間的關係也就不那麼的緊密了, 換句話說, 只要是有open_door()方法的對象.  均可以接收運行
        ref.open_door()
  
    def close(self, ref):
        print("大象要關門了. 默唸三聲. 關!")
        pass
    def take(self):
        print("鑽進去")
 
class Refrigerator:
    def open_door(self):
        print("冰箱門被打開了")
    def close_door(self):
        print("冰箱門被關上了")
# 造冰箱
r = Refrigerator()
# 造大象
el = Elphant("神奇的大象")
el.open(r) # 注意,此時是把一個冰箱做爲參數傳遞進去了,也就是說,大象能夠指定任何一個冰箱.
el.take()
el.close(r)

此時咱們說, 大象和冰箱之間就是依賴關係,我用着你,可是你不屬於我, 這種關係是最弱的.好比,公司和僱員之間,對於正式員工, 確定要簽定勞動合同, 還得當心伺候着,可是若是是兼職,那無所謂,須要了你就來,不須要你就能夠拜拜了. 這裏的兼職(臨時工) 就屬於依賴關係,我用你可是你不屬於我.

二.關聯關係.組合關係.聚合關係

其實這三個在代碼上寫法是同樣的. 可是, 從含義上是不同的.

  1. 關聯關係: 兩種事物必須是互相關聯的,可是在某些特殊狀況下是能夠更改和更換的

  2. 聚合關係: 屬於關聯關係中的一種特例,側重點是xxx和xxx聚合成xxx. 各自有各自的聲明週期, 好比電腦,電腦裏有CPU, 硬盤, 內存等等,電腦掛了, CPU仍是好的,仍是完整的個體

  3. 組合關係: 屬於關聯關係中的一種特例, 寫法上差很少,組合關係比聚合還要緊密,好比人的大腦, 心臟, 各個器官. 這些器官組合成一我的. 這時人若是掛了,其餘的東西也跟着掛了.
    首先咱們看關聯關係: 這個最簡單,也是最經常使用的一種關係. 好比,你們都有男女友,男人關聯着女友,女人關聯着男友. 這種關係能夠是互相的, 也能夠是單方面的.

#Python學習交流羣:778463939

class Boy:
    def __init__(self, name, girlFriend=None):
        self.name = name
        self.girlFriend = girlFriend
 
    def have_a_dinner(self):
        if self.girlFriend:
            print("%s 和 %s⼀起去吃晚餐" % (self.name, self.girlFriend.name))
        else:
            print("單身狗. 吃什麼飯")
 
class Girl:
    def __init__(self, name):
        self.name = name
 
b = Boy("alex")
b.have_a_dinner()
 
# 忽然牛B了. 找到女友了
g = Girl("如花")
b.girlFriend = g # 有女友了. 6666
b.have_a_dinner()
 
gg = Girl("李小花")
bb = Boy("wusir", gg) # 娃娃親. 出生就有女友. 服不服
 
bb.have_a_dinner() # 多麼幸福的一家
 
# 忽然.bb失戀了. 娃娃親不跟他好了
bb.girlFriend = None
 
bb.have_a_dinner() # 又單身了

注意,此時Boy和Girl兩個類之間就是關聯關係,兩個類的對象緊密聯繫着, 其中一個沒有了,另外一個就孤單的不得了, 關聯關係, 其實就是我須要你, 你也屬於我,這就是關聯關係. 像這樣的關係有不少不少,好比,學校和老師之間的關係.

  • School --- 學校

  • Teacher--- 老師

老師必然屬於一個學校,換句話說,每一個老師確定有一個指定的工做機構, 就是學校. 那老師的屬性中必然關聯着學校

class School:
    def __init__(self, name, address):
        self.name = name
        self.address = address
 
class Teacher:
    def __init__(self, name, school=None):
        self.name = name
        self.school = school
 
s1 = School("北京", "沙河")
s2 = School("上海", "迪士尼")
s3 = School("深圳", "南山區法院")
t1 = Teacher("白金", s1)
t2 = Teacher("黃金", s1)
t3 = Teacher("白銀", s2)
t4 = Teacher("青銅", s3)
 
# 找到青銅所在的地址
print(t4.school.address)

想一想, 這樣的關係若是反過來,一個老師能夠選一個學校任職, 那反過來, 一個學校有多少老師呢? 一堆吧? 這樣的關係如何來描述呢?

class School:
    def __init__(self, name, address):
        self.name = name
        self.address = address
        self.t_list = [] # 每一個學校都應該有一個裝一堆老師的列表
 
    def add_teacher(self, teacher):
        self.t_list.append(teacher)
 
class Teacher:
    def __init__(self, name, school=None):
        self.name = name
        self.school = school
s1 = School("北京", "沙河")
s2 = School("上海", "迪士尼")
s3 = School("深圳", "南山區法院")
 
t1 = Teacher("白金", s1)
t2 = Teacher("黃金", s1)
t3 = Teacher("白銀", s2)
t4 = Teacher("青銅", s3)
 
s1.add_teacher(t1)
s1.add_teacher(t2)
s1.add_teacher(t3)
 

for t in s1.t_list:
    print(t.name)

好了,這就是關聯關係,當咱們在邏輯上出現了, 我須要你,你還得屬於我,這種邏輯就是關聯關係. 那注意,這種關係的緊密程度比上面的依賴關係要緊密的多,爲何呢? 想一想吧

至於組合關係和聚合關係,其實代碼上的差異不大,都是把另外一個類的對象做爲這個類的屬性來傳遞和保存, 只是在含義上會有些許的不一樣而已.

三.繼承關係

在面向對象的世界中存在着繼承關係,咱們現實中也存在着這樣的關係, 咱們說過,x是一種y, 那x就能夠繼承y. 這時理解層面上的,若是上升到代碼層面,咱們能夠這樣認爲, 子類在不影響父類的程序運行的基礎上對父類進行的擴充和擴展. 這裏咱們能夠把父類稱爲超類或者基類,子類被稱爲派生類.

首先, 類名和對象默認是能夠做爲字典的key的

class Foo:
    def __init__(self):
        pass
    def method(self):
        pass
    # __hash__ = None
 
print(hash(Foo))
print(hash(Foo()))

既然能夠hash, 那就是說字典的key能夠是對象或者類

dic = {}
dic[Foo] = 123
dic[Foo()] = 456
print(dic) # {<class '__main__.Foo'>: 123, <__main__.Foo object at0x103491550>: 456}

雖然顯示的有點兒詭異,可是是能夠用的.

接下來,咱們來繼續研究繼承上的相關內容. 在本節中主要研究一下self,記住,無論方法之間如何進行調用, 類與類之間是何關係, 默認的self都是訪問這個方法的對象.

#Python學習交流羣:778463939

class Base:
    def __init__(self, num):
        self.num = num
 
    def func1(self):
        print(self.num)
 
class Foo(Base):
    pass
 
obj = Foo(123)
obj.func1() # 123 運行的是Base中的func1

繼續:

class Base:
    def __init__(self, num):
        self.num = num
 
    def func1(self):
        print(self.num)
 
class Foo(Base):
    def func1(self):
        print("Foo. func1", self.num)
 
obj = Foo(123)
obj.func1() # Foo. func1 123 運行的是Foo中的func1

再來:

class Base:
    def __init__(self, num):
        self.num = num
 
    def func1(self):
        print(self.num)
        self.func2()
 
    def func2(self):
        print("Base.func2")
 
class Foo(Base):
    def func2(self):
        print("Foo.func2")
 
obj = Foo(123)
obj.func1() # 123 Foo.func2 func1是Base中的 func2是子類中的

總結:self在訪問方法的順序: 永遠先找本身的,本身的找不到再找父類的.

接下來. 來可貴:

class Base:
    def __init__(self, num):
        self.num = num
 
    def func1(self):
        print(self.num)
        self.func2()
 
    def func2(self):
        print(111, self.num)
 
class Foo(Base):
    def func2(self):
        print(222, self.num)
 
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
    obj.func2() # 111 1 | 111 2 | 222 3

再來,還不夠繞.

#Python學習交流羣:778463939

class Base:
    def __init__(self, num):
        self.num = num
 
    def func1(self):
        print(self.num)
        self.func2()
 
    def func2(self):
        print(111, self.num)
 
class Foo(Base):
    def func2(self):
        print(222, self.num)
 
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
 obj.func1() # 拿筆來吧. 好好算

結論: self就是你訪問方法的那個對象,先找本身, 而後在找父類的

四.類中的特殊成員

什麼是特殊成員呢? __init_()就是一 個特殊的成員,說白了,帶雙下劃線的那一坨,這些方法在特殊的場景的時候會被自動的執行. 好比,

  1. 類名() 會自動執行__init__()

  2. 對象() 會自動執行__call__()

  3. 對象[key] 會自動執行__getitem__()

  4. 對象[key] = value 會自動執行__setitem__()

  5. del 對象[key] 會自動執行 __delitem__()

  6. 對象+對象 會自動執行 __add__()

  7. with 對象 as 變量 會自動執行__enter__ __exit__

  8. 打印對象的時候 會自動執行 __str__

  9. 幹掉可哈希 __hash__ == None 對象就不可哈希了.

  10. abs(對象) 會自動執行__abs__()

  11. bool(對象)會自動執行__bool__()

  12. bytes(對象)會自動執行__bytes__()

  13. float(對象)會自動執行__float__()

  14. int(對象)會自動執行__int__()

  15. 對象.index()會自動執行__index__()

  16. len(對象)會自動執行__len__()

  17. next() 會自動執行__next__()

  18. repr()會自動執行__repr__()

  19. round(對象)會自動執行__round__()

  20. copy.對象會自動執行__copy__()

建立對象的真正步驟:

首先, 在執行類名()的時候,系統會自動先執行__new__()來開闢內存. 此時新開闢出來的內存區域是空的, 緊隨其後, 系統自動調用__init__()來完成對象的初始化工做,按照時間軸來算.

  1. 加載類

  2. 開闢內存(__new__)

  3. 初始化(__init__)

  4. 使用對象幹xxxxxxxxx

相似的操做還有不少不少,咱們不須要徹底刻意的去把全部的特殊成員全都記住,實戰中也用不到那麼多, 用到了查就是了.

相關文章
相關標籤/搜索