1. 程式人生 > >python類與類之間的關係

python類與類之間的關係

在面向物件中,類和類之間也可以產生相關的關係
類中的關係: 依賴關係是最輕的,最重的是繼承關係,關聯關係是比較微妙的

依賴關係
執行某個動作的時候,需要xxx來幫助完成這個操作,此時的關係是最輕的.
隨時可以更換另外一個東西來完成此操作

複製程式碼
 1 class Person:
 2     def f1(self,tools):     # 通過引數的傳遞把另外一個類的物件傳遞進來
 3         tools.run()
 4         print('皮一下很開心')
 5 class Computer:
 6     def run(self):
 7         print('電腦開機執行')
 8 class Phone:
 9     def run(self):
10         print('手機開機')
11 c = Computer()
12 a = Phone()
13 p = Person()
14 p.f1(a)         #把Phone類的物件a傳遞給Person的f1方法作為引數
15 結果
16 手機開機
17 皮一下很開心
18 
19 事例二
20 植物大戰殭屍
21 class Plant:
22     def __init__(self,hp,ad):
23         self.hp = hp
24         self.ad = ad
25     def attack(self,js):
26         print('植物攻擊殭屍')
27         js.hp -= self.ad
28         print(f'殭屍掉血{self.ad},剩餘{js.hp}')
29 class JiangShi:
30     def __init__(self,hp,ad):
31         self.hp = hp
32         self.ad = ad
33     def attack(self,zw):
34         print('殭屍咬植物')
35         zw.hp -= self.ad
36         print(f'植物掉血{self.ad},剩餘{zw.hp}')
37 zw = Plant(100,11)
38 js = JiangShi(80,15)
39 zw.attack(js)
40 zw.attack(js)
41 js.attack(zw)
42 js.attack(zw)
43 結果
44 植物攻擊殭屍
45 殭屍掉血11,剩餘69
46 植物攻擊殭屍
47 殭屍掉血11,剩餘58
48 殭屍咬植物
49 植物掉血15,剩餘85
50 殭屍咬植物
51 植物掉血15,剩餘70
複製程式碼

關聯關係
物件裡面包含物件

複製程式碼
 1 一對一關係
 2 class Boy:
 3     def __init__(self,name,girFriend=None):
 4         self.name = name
 5         self.girFriend = girFriend
 6     def play(self):
 7         if self.girFriend:
 8             print(f'{self.name}帶著他女朋友{self.girFriend.name}去吃飯')
 9         else:
10             print('單身狗,還吃什麼飯')
11     def movie(self):
12         if self.girFriend:
13             print(f'{self.name}帶著他女朋友{self.girFriend.name}去看電影')
14         else:
15             print('單身狗,還看什麼電影')
16 class Girl:
17     def __init__(self,name):
18         self.name = name
19 b = Boy('劉昊然')
20 g = Girl('劉麗')
21 b.play()
22 
23 b.girFriend = g
24 b.play()
25 
26 g2 = Girl('王萌')
27 b.girFriend = g2
28 b.movie()
29 
30 
31 一對多關係
32 self.teach_list = [t1,t2,...]
33 class School:
34     def __init__(self,name):
35         self.teach_list = []
36     def zhaopin(self,teach):
37         self.teach_list.append(teach)
38     def shangke(self):
39         for i in self.teach_list:
40             i.work()
41 class Teacher:
42     def __init__(self,name):
43         self.name = name
44     def work(self):
45         print(f'{self.name}在上課')
46 lnh = School('測試')
47 t1 = Teacher('趙老師')
48 t2 = Teacher('劉老師')
49 lnh.zhaopin(t1)
50 lnh.zhaopin(t2)
51 lnh.shangke()
52 結果
53 趙老師在上課
54 劉老師在上課
複製程式碼

繼承關係

複製程式碼
 1 class Base:         #父類又叫基類又叫超類
 2     def chi(self):
 3         print('吃飯')
 4 class Foo(Base):    #子類又叫派生類,這個類繼承了Base類,Foo類是對Base的一個擴充套件
 5     def he(self):
 6         print('喝水')
 7 f = Foo()
 8 f.chi()
 9 f.he()
10 print(hash(Foo))    #預設類和建立的物件都是可雜湊的
11 print(hash(Foo()))
12 結果
13 吃飯
14 喝水
15 -9223371912599947772
16 -9223371912597968945
17 
18 去掉可雜湊
19 __hash__ = None
20 class Base:
21     def chi(self):
22         print('吃飯')
23 class Foo(Base):
24     __hash__ = None     # 當前類的物件不可雜湊
25     def he(self):
26         print('喝水')
27 f = Foo()
28 f.chi()
29 f.he()
30 print(hash(Foo))    # 類名永遠可雜湊
31 print(hash(Foo()))  # TypeError: unhashable type: 'Foo'
複製程式碼

類名相當於變數名

複製程式碼
 1 class Foo:
 2     def chi(self,food):
 3         print('吃魚和',food)
 4 class Bar:
 5     def chi(self,food):
 6         print('吃肉和',food)
 7 dic = {Foo:'麵包',Bar:'牛奶'}
 8 for k,v in dic.items():
 9     k().chi(v)
10 結果
11 吃魚和 麵包
12 吃肉和 牛奶
複製程式碼

練習

複製程式碼
 1 事例1
 2 class Base:
 3     def __init__(self, num):
 4         self.num = num
 5 
 6     def func1(self):
 7         print(self.num)
 8         self.func2()
 9 
10     def func2(self):
11         print(111, self.num)
12 
13 class Foo(Base):
14     def func2(self):
15         print(222, self.num)
16 
17 lst = [Base(1), Base(2), Foo(3)]
18 for obj in lst:
19     obj.func2()
20 結果
21 111 1
22 111 2
23 222 3
24 
25 事例2
26 class Base:
27     def __init__(self, num):
28         self.num = num
29     def func1(self):
30         print(self.num)
31         self.func2()
32     def func2(self):
33         print(111, self.num)
34 
35 class Foo(Base):
36     def func2(self):
37         print(222, self.num)
38 
39 lst = [Base(1), Base(2), Foo(3)]
40 for obj in lst:
41     obj.func1()
42 結果
43 1
44 111 1
45 2
46 111 2
47 3
48 222 3
複製程式碼

self:誰呼叫的就是誰,型別是根據呼叫方的物件來進行變換的
super:表示的是父類

特殊成員:
__init__()  # 建立物件的時候初始化操作
__call__()  # 物件()
__getitem__()   # 物件[哈哈]
__setitem__()   # 物件[哈哈] = 值
__new__()   # 建立物件的時候.開闢記憶體
__hash__()  # 可雜湊 hash()

複製程式碼
  1 __call__ 
  2 物件後面加括號,觸發執行
  3 注:構造方法的執行是由建立物件觸發的,即:物件 = 類名() ;而對於 __call__ 方法的執行是由物件後加括號觸發的,即:物件() 或者 類()()
  4 class Foo:
  5     def __init__(self):
  6         pass
  7 
  8     def __call__(self, *args, **kwargs):
  9         print('__call__')
 10 
 11 obj = Foo()  # 執行 __init__
 12 obj()  # 執行 __call__
 13 結果
 14 __call__
 15 
 16 事例2
 17 class Foo:
 18     def __init__(self):                 # 初始化操作
 19         print('我是init,我是第二')
 20 
 21     def __new__(cls, *args, **kwargs):  # 建立,是真正的構造方法,可以開闢記憶體
 22         print('我是new,我是第一')
 23         return object.__new__(cls)
 24 
 25     def __call__(self, *args, **kwargs): # 物件()   
 26         print('我是物件call')
 27 
 28     def __getitem__(self, item):        # 物件[]
 29         print('item',item)
 30         print('我是getite')
 31 
 32     def __setitem__(self, key, value):  # 物件[key] = value
 33         print('key',key)
 34         print('value',value)
 35 Foo()
 36 f = Foo()          # 自動執行__init__()
 37 f()                # 呼叫__call__()
 38 print(callable(f)) # 物件()
 39 print(f['娃哈哈']) #自動呼叫__getitem__()
 40 f['人']='劉麗'     #自動的呼叫__getitem__()
 41 結果
 42 我是new,我是第一
 43 我是init,我是第二
 44 我是new,我是第一
 45 我是init,我是第二
 46 我是物件call
 47 True
 48 item 娃哈哈
 49 我是getite
 50 None
 51 key 人
 52 value 劉麗
 53 
 54 
 55 事例3
 56 class Foo:
 57     def __init__(self,name):
 58         self.name=name
 59 
 60     def __getitem__(self, item):
 61         print(self.__dict__[item])
 62 
 63     def __setitem__(self, key, value):
 64         self.__dict__[key]=value
 65     def __delitem__(self, key):
 66         print('del obj[key]時,我執行')
 67         self.__dict__.pop(key)
 68     def __delattr__(self, item):
 69         print('del obj.key時,我執行')
 70         self.__dict__.pop(item)
 71 
 72 f1=Foo('sb')
 73 f1['age']=18
 74 f1['age1']=19
 75 print(f1.__dict__)
 76 del f1.age1
 77 del f1['age']
 78 f1['name']='alex'
 79 print(f1.__dict__)
 80 結果
 81 {'name': 'sb', 'age': 18, 'age1': 19}
 82 del obj.key時,我執行
 83 del obj[key]時,我執行
 84 {'name': 'alex'}
 85 
 86 
 87 事例4
 88 class Person:
 89     def __init__(self,name,age):
 90         self.name = name
 91         self.age = age
 92     #這個物件字串的表示
 93     def __str__(self):  #返回該物件的字串表示形式
 94         return f'{self.name},{self.age}'
 95     def __repr__(self):  #該物件的官方的字串表示形式
 96         return f'{self.name},{self.age}'
 97 s = Person('bob','18')
 98 print(s)
 99 結果
100 bob,18
101 
102 事例5
103 class B:
104     def __str__(self):
105         return 'str : class B'
106     def __repr__(self):
107         return 'repr : class B'
108 b = B()
109 print('%s' % b)     #這個執行的是__str__函式方法
110 print('%r' % b)     #這個執行的是__repr__函式方法
111 結果
112 str : class B 
113 repr : class B
114 
115 
116 __del__
117 析構方法,當物件在記憶體中被釋放時,自動觸發執行
118 注:此方法一般無須定義,因為Python是一門高階語言,程式設計師在使用時無需關心記憶體的分配和釋放,因為此工作都是交給Python直譯器來執行,所以,解構函式的呼叫是由直譯器在進行垃圾回收時自動觸發執行的。
119 class Foo:
120 
121     def __del__(self):
122         print('執行我啦')
123 
124 f1=Foo()
125 del f1
126 print('------->')
127 結果
128 執行我啦
129 ------->