2.面向對象:類空間問題以及類之間的關係

  • 2019 年 10 月 3 日
  • 筆記

一. 類的空間問題

1.1 何處可以添加對象屬性

class A:      def __init__(self,name):          self.name = name        def func(self,sex):          self.sex = sex
# 類外面可以:  obj = A('barry')  obj.age = 18  print(obj.__dict__)  # {'name': 'barry', 'age': 18}    # 類內部也可以:  obj = A('barry') # __init__方法可以。  obj.func('男')  # func 方法也可以。

**總結:對象的屬性不僅可以在__init__裡面添加,還可以在類的其他方法或者類的外面添加。**

1.2 何處可以添加類的靜態屬性

class A:      def __init__(self,name):          self.name = name        def func(self,sex):          self.sex = sex        def func1(self):          A.bbb = 'ccc'
# 類的外部可以添加    A.aaa = 'taibai'  print(A.__dict__)    # 類的內部也可以添加。    A.func1(111)  print(A.__dict__)

總結:類的屬性不僅可以在類內部添加,還可以在類的外部添加。

1.3 對象如何找到類的屬性

之前咱們都學習過,實例化一個對象,可以通過點的方式找到類中的屬性,那麼他為什麼可以找到類中的屬性呢?

通過圖解說明:

img

對象查找屬性的順序:先從對象空間找 ——> 類空間找 ——> 父類空間找 ——->…..

類名查找屬性的順序:先從本類空間找 ——-> 父類空間找——–> ……..

上面的順序都是單向不可逆,類名不可能找到對象的屬性。

二. 類與類之間的關係

⼤千世界, 萬物之間皆有規則和規律. 我們的類和對象是對⼤千世界中的所有事物進⾏歸類. 那事物之間存在著相對應的關係. 類與類之間也同樣如此. 在⾯向對象的世界中. 類與類中存在以下關係:

1. 依賴關係
2. 關聯關係
3. 組合關係
4. 聚合關係
5. 實現關係
6. 繼承關係(類的三大特性之一:繼承。)

2.1 依賴關係

⾸先, 我們設計⼀個場景. 還是最初的那個例⼦. 要把⼤象裝冰箱. 注意. 在這個場景中, 其實是存在了兩種事物的. ⼀個是⼤象, ⼤象負責整個事件的掌控者, 還有⼀個是冰箱, 冰箱負責被⼤象操縱.

⾸先, 寫出兩個類, ⼀個是⼤象類, ⼀個是冰箱類

class Elphant:      def __init__(self, name):          self.name = name        def open(self):          '''          開⻔          '''          pass        def close(self):          '''          關⻔          '''          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,obj1):          '''          開⻔            '''          print('大象要開門了,默念三聲,開')          obj1.open_door()        def close(self):          '''          關⻔          '''          print('大象要關門了,默念三聲,關')      class Refrigerator:        def open_door(self):          print("冰箱⻔被打開了")        def close_door(self):          print("冰箱⻔被關上了")      elphant1 = Elphant('大象')  haier = Refrigerator()  elphant1.open(haier)

  動作發起的主體是大象,你們把關門這個練一下。依賴關係:將一個類的對象或者類名傳到另一個類的方法使用。此時, 我們說, ⼤象和冰箱之間就是依賴關係. 我⽤著你. 但是你不屬於我. 這種關係是最弱的.比如. 公司和僱員之間. 對於正式員⼯, 肯定要簽訂勞動合約. 還得⼩⼼伺候著. 但是如果是兼職. 那⽆所謂. 需要了你就來. 不需要你就可以拜拜了. 這⾥的兼職(臨時⼯) 就屬於依賴關係.我⽤你. 但是你不屬於我

2.2 關聯,聚合,組合關係

其實這三個在程式碼上寫法是⼀樣的. 但是, 從含義上是不⼀樣的.

1. 關聯關係. 兩種事物必須是互相關聯的. 但是在某些特殊情況下是可以更改和更換的.

2. 聚合關係. 屬於關聯關係中的⼀種特例. 側重點是xxx和xxx聚合成xxx. 各⾃有各⾃的聲明周期. 比如電腦. 電腦⾥有CPU, 硬碟, 記憶體等等. 電腦掛了. CPU還是好的. 還是完整的個體

3. 組合關係. 屬於關聯關係中的⼀種特例. 寫法上差不多. 組合關係比聚合還要緊密. 比如⼈的⼤腦, ⼼臟, 各個器官. 這些器官組合成⼀個⼈. 這時. ⼈如果掛了. 其他的東⻄也跟著掛了

  先看關聯關係:

這個最簡單. 也是最常⽤的⼀種關係. 比如. ⼤家都有男女朋友. 男⼈關聯著女朋友. 女⼈關聯著男朋友. 這種關係可以是互相的, 也可以是單⽅⾯的.

class Boy:      def __init__(self,name,girlFriend=None):          self.name = name          self.girlFriend = girlFriend        def have_a_diner(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('日天')  b.have_a_diner() # 此時是單身狗    # 突然有一天,日天牛逼了  b.girlFriend = '如花'  b.have_a_diner()  #共進晚餐
# wusir 生下來就有女朋友 服不服  gg = Girl('小花')  bb = Boy('wusir', gg)  bb.have_a_diner()    # 結果嫌他有點娘,不硬,分了  bb.girlFriend = None  bb.have_a_diner()

注意. 此時Boy和Girl兩個類之間就是關聯關係. 兩個類的對象緊密練習著. 其中⼀個沒有了. 另⼀個就孤單的不得了. 關聯關係, 其實就是 我需要你. 你也屬於我. 這就是關聯關係. 像這樣的關係有很多很多. 比如. 學校和老師之間的關係.

# 老師屬於學校,必須有學校才可以工作  class School:        def __init__(self,name,address):          self.name = name          self.address = address      class Teacher:        def __init__(self,name,school):          self.name = name          self.school = school    s1 = School('北京校區','美麗的沙河')  s2 = School('上海校區','上海迪士尼旁邊')  s3 = School('深圳校區','南山區')    t1 = Teacher('武大',s1)  t2 = Teacher('海峰',s2)  t3 = Teacher('日天',s3)    print(t1.school.name)  print(t2.school.name)  print(t3.school.name)

但是學校也是依賴於老師的,所以老師學校應該互相依賴。

class School:        def __init__(self,name,address):          self.name = name          self.address = address          self.teacher_list = []        def append_teacher(self,teacher):          self.teacher_list.append(teacher)    class Teacher:        def __init__(self,name,school):          self.name = name          self.school = school    s1 = School('北京校區','美麗的沙河')  s2 = School('上海校區','上海迪士尼旁邊')  s3 = School('深圳校區','南山區')    t1 = Teacher('武大',s1)  t2 = Teacher('海峰',s2)  t3 = Teacher('日天',s3)    s1.append_teacher(t1)  s1.append_teacher(t2)  s1.append_teacher(t3)    # print(s1.teacher_list)  # for teacher in s1.teacher_list:  #     print(teacher.name)

好了. 這就是關聯關係. 當我們在邏輯上出現了. 我需要你. 你還得屬於我. 這種邏輯 就是關聯關係. 那注意. 這種關係的緊密程度比上⾯的依賴關係要緊密的多. 為什麼呢? 想想吧

至於組合關係和聚合關係,其實程式碼上差別不大,咱們就以組合舉例:

組合:將一個類的對象封裝到另一個類的對象的屬性中,就叫組合。

咱們設計一個遊戲人物類,讓實例化幾個對象讓這幾個遊戲人物實現互毆的效果。

class Gamerole:      def __init__(self,name,ad,hp):          self.name = name          self.ad = ad          self.hp = hp      def attack(self,p1):          p1.hp -= self.ad          print('%s攻擊%s,%s掉了%s血,還剩%s血'%(self.name,p1.name,p1.name,self.ad,p1.hp))  gailun = Gamerole('蓋倫',10,200)  yasuo= Gamerole('亞索',50,80)    #蓋倫攻擊亞索  gailun.attack(yasuo)  # 亞索攻擊蓋倫  yasuo.attack(蓋倫)

但是這樣互相攻擊沒有意思,一般遊戲類的的對戰方式要藉助武器,武器是一個類,武器類包含的對象很多:刀槍棍劍斧鉞鉤叉等等,所以咱們要寫一個武器類。

class Gamerole:      def __init__(self,name,ad,hp):          self.name = name          self.ad = ad          self.hp = hp      def attack(self,p1):          p1.hp -= self.ad          print('%s攻擊%s,%s掉了%s血,還剩%s血'%(self.name,p1.name,p1.name,self.ad,p1.hp))    class Weapon:      def __init__(self,name,ad):          self.name = name          self.ad = ad      def weapon_attack(self,p1,p2):          p2.hp = p2.hp - self.ad - p1.ad          print('%s 利用 %s 攻擊了%s,%s還剩%s血' %(p1.name,self.name,p2.name,p2.name,p2.hp))

接下來藉助武器攻擊對方:

pillow = Weapon('繡花枕頭',2)  pillow.weapon_attack(barry,panky)  # 但是上面這麼做不好,利用武器攻擊也是人類是動作的發起者,所以不能是pillow武器對象,而是人類利用武器攻擊對方

所以,對程式碼進行修改。

class Gamerole:      def __init__(self,name,ad,hp):          self.name = name          self.ad = ad          self.hp = hp      def attack(self,p1):          p1.hp -= self.ad          print('%s攻擊%s,%s掉了%s血,還剩%s血'%(self.name,p1.name,p1.name,self.ad,p1.hp))        def equip_weapon(self,wea):          self.wea = wea  # 組合:給一個對象封裝一個屬性改屬性是另一個類的對象  class Weapon:      def __init__(self,name,ad):          self.name = name          self.ad = ad      def weapon_attack(self,p1,p2):          p2.hp = p2.hp - self.ad - p1.ad          print('%s 利用 %s 攻擊了%s,%s還剩%s血'                %(p1.name,self.name,p2.name,p2.name,p2.hp))      # 實例化三個人物對象:  barry = Gamerole('太白',10,200)  panky = Gamerole('金蓮',20,50)  pillow = Weapon('繡花枕頭',2)    # 給人物裝備武器對象。  barry.equip_weapon(pillow)    # 開始攻擊  barry.wea.weapon_attack(barry,panky)

上面就是組合,只要是人物.equip_weapon這個方法,那麼人物就封裝了一個武器對象,再利用武器對象調用其類中的weapon_attack方法。

在python中類的實現關係和類的繼承是一個意思