Class Variables 演練與變數記憶體關係範例
class Counter:
total = 0
測試重點詳解:
類別變數 total 的定義與初始化:
程式碼執行過程:
a = Counter():建立第一個物件,Counter.total 變為 0 + 1 = 1。
b = Counter():建立第二個物件,Counter.total 變為 1 + 1 = 2。
c = Counter():建立第三個物件,Counter.total 變為 2 + 1 = 3。
最終輸出:
print(Counter.total) 最終會輸出 3。
Counter.total=0, id=10914880 <-- id(0)
total = 0
def __init__(self):
Counter.total += 1
a = Counter()
b = Counter()
c = Counter()
print(Counter.total)
a = Counter()
b = Counter()
c = Counter()
print(Counter.total)
測試重點詳解:
類別變數 total 的定義與初始化:
- total = 0 定義在 class Counter: 區塊內,而不是在任何方法(如 __init__)中,這使得 total 成為一個類別變數。
- 特性: 所有透過 Counter 類別建立的物件(實例,如 a、b、c)都會共享這同一個 total 變數。
- def __init__(self): 是在物件被建立時自動呼叫的方法。
- Counter.total += 1 確保了每當一個 Counter 類別的物件被建立時,共享的類別變數 total 的值就會增加 1。
程式碼執行過程:
a = Counter():建立第一個物件,Counter.total 變為 0 + 1 = 1。
b = Counter():建立第二個物件,Counter.total 變為 1 + 1 = 2。
c = Counter():建立第三個物件,Counter.total 變為 2 + 1 = 3。
最終輸出:
print(Counter.total) 最終會輸出 3。
但是,更進階一點,如果程式寫成下面的方式
class Counter:
total = 0
def __init__(self):
print(f"Counter.total={Counter.total}, id={id(Counter.total)}")
Counter.total += 1
self.total += 2
print(f"self.total={self.total}, id={id(self.total)}")
a = Counter()
b = Counter()
c = Counter()
print(Counter.total)
print(a.total)
print(b.total)
print(c.total)
這時使用 self.total,就是以當時被建立的實力底下的 total來做計算。所以, a, b, c 三個個別的實例,會因為當時共用的 Counter.total 所計算的結果再進行一次 "+2" 的動作。
所以輸出結果會變成:
self.total=3, id=10914976 <-- id(3) (a.total)
Counter.total=1, id=10914912 <-- id(1) (新的整數物件)
self.total=4, id=10915008 <-- id(4) (b.total)
Counter.total=2, id=10914944 <-- id(2) (新的整數物件)
所以
直接調用 Counter.total 和 Counter() 呼叫後,調用其中的 a.total 意義是不同的。
而在自己類別當中使用的意義也是不一樣的。
所以要特別記清楚!!
留言
張貼留言