Python 16 類與類之間的關係
類與類之間的關係
類與類之間的關係
類與類中存在的關係:
1.依賴關係
2.關聯關係
3.組合關係
4.聚合關係
5.繼承關係
6.實現關係
python是一門弱型別程式語言,並且所有的物件之間其實都是多型關係,所有的東西都可以當做物件來使用。
一.依賴關係
依賴關係:我需要用你,但你不屬於我,這種關係是最弱的。
例:把大象裝進冰箱,建立大象、冰箱兩個類
class Elephant:
def init(self,name):
self.name = name
def open(self,ref): print('大象說:開門吧') ref.open_door() def close(self,ref): print('大象說:關門吧') ref.close_door() def take(self): print('大象走進冰箱')
class BingXiang:
def open_door(self):
print('冰箱:門開了')
def close_door(self):
print('冰箱:關好了')
r = BingXiang() # 造冰箱
el = Elephant('獨立自主的大象') # 造大象
el.open(r) # 把冰箱當作引數傳遞進大象的類中,大象可以指定任何一個冰箱去進行操作
el.take()
el.close(r)
二.關聯關係、組合關係、聚合關係
1.關聯關係:兩種事物必須是相互關聯的,但是在某些特殊情況下是可以更改的和更換的。
2.聚合關係:屬於關聯關係中的一種特例,重點是xxx和xxx聚合城了xxx,各自有各自的宣告週期,主體完蛋了,個體依然存在。
3.組合關係:屬於關聯關係中的一種特例,寫法上差不多,組合關係比聚合關係還要緊密,主體完蛋了,個體跟著一起完蛋。
例:
男女朋友關係,可以是相互的也可以是單方面的
class Boy:
def init(self,name,girlFriend = None):
self.name = name
self.girlFriend = girlFriend
def yujian(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.yujian() g = Girl('王婆') b.girlFriend = g # 有女朋友了 b.yujian() # 兩個人一起吃飯
注:關聯關係在邏輯上出現了,我需要你,你還要屬於我,這種邏輯就是關聯關係。
組合關係和聚合關係,程式碼上的差別不大,都是把另一類的物件作為這個類的屬性來傳遞和儲存,只是在含以上有不同。
三:繼承關係
繼承關係:子類在不影響父類的程式執行的基礎上對父類進行擴充和擴充套件,我們可以父類成為超類或者基類,子類被稱為派生類。
例:類名和物件預設是可以作為字典的key的
class Foo:
def __init__(self):
pass
def method(self):
pass
print(hash(Foo))
print(hash(Foo()))
# 既然可hash,那就說明字典的key可以是物件或者類
dic = {}
dic[Foo] = 123
dic[Foo()] = 456
print(dic) # {<class '__main__.Foo'>: 123, <__main__.Foo object at 0x00000000021D82E8>: 456}
四:self
接下來研究繼承上的相關內容,主要研究self(不關方法之間如何進行呼叫,類與類之間是何關係,
預設的self都是訪問這個方法的物件)
例1:
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
例2:
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
總結:self在訪問方法的順序:永遠都是先找自己,自己找不到再到父類裡找。
例3:
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
例4:
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() # 1 111 1 | 2 111 2 | 3 222 3
總結:self就是你訪問方法的那個物件,先找自己的,然後在找父類的。
五:類中的特殊成員
像__init__()這樣,帶上下劃線的方法就屬於特殊成員,在特殊的場景會被自動執行。
例:
- 類名() 會自動執行__init__()
- 物件() 會自動執行__call__()
- 物件[key] 會自動執行__getitem__()
- 物件[key] = value 會自動執行__setitem__()
- del 物件[key] 會自動執行 delitem()
- 物件+物件 會自動執行 add()
- with 物件 as 變數 會自動執行__enter__ 和__exit__
- 列印物件的 時候 會自動執行 str
- 幹掉可雜湊 hash == None 物件就不可雜湊了.
建立物件的真正步驟:
首先, 在執行類名()的時候,系統會自動先執⾏__new__()來開闢記憶體,此時新開闢出來的記憶體區域是空的。
緊隨其後系統⾃自動呼叫__init__()來完成物件的初始化操作,按照時間軸來算。
1.載入類
2.開闢記憶體(new)
3.初始化(init)
4.使用物件去執行什麼