Python 其實不是物件導向的語言,更像是C語言的程式導向程式設計的語言
但 Python 也支援 class 關鍵字來實現類的宣告與建立
但 Python 的物件更像是 JavaScript 的函式
遇到的問題 #1
-- 正確的程式碼
class Person: user_account = None name = None days = None months = None abnormal_days = 0 total_hours = 0 total_work_overtime = 0 total_late_hours = 0 def __init__(self, user_acount, name): self.user_account = user_acount self.name = name self.days = [] self.months = [] # 增加12個月的month_record 物件 for i in range(1, 13): self.months.append(date_process.MonthRecord(i)) print(len(self.months))
-- 錯誤的程式碼
class Person: user_account = None name = None days = None months = [] abnormal_days = 0 total_hours = 0 total_work_overtime = 0 total_late_hours = 0 def __init__(self, user_acount, name): self.user_account = user_acount self.name = name self.days = [] # 增加12個月的month_record 物件 for i in range(1, 13): self.months.append(date_process.MonthRecord(i)) print(len(self.months))
這兩段程式碼的查詢在於 months 變數,在正確的程式碼裡,成員變數的定義裡寫成了 months = None, months = [ ] 寫在了 __init__() 函式裡面, 而在錯誤的程式碼裡寫成了 months = [ ]。錯誤的程式碼產生的影響是什麼呢?
-----------
當你建立一個新的 Person 物件 first_person 時候,在開始執行 __init__() 函式的時候(即是執行到
self.user_account = user_acount
這一步的時候),months 的物件是 [ ]
當你建立第二個 Person 物件 secong_person 的時候,第二次執行 __init__() 函式的時候,months 的物件是 first_person.month(),其引用的其實同一塊記憶體區域的值。
這個地方非常的反直覺,造成的後果也非常大,我為了排查這個錯誤也花了很久的時間。
--------- 一點猜測
只是猜測而已,沒有進行過詳細的驗證
pyhthon 的 class 其實只是一個類似JS的函式物件,這個函式有自己的記憶體空間,但是實際上類就像一個函式,每一次引用的的時候都是調取的同一塊記憶體區域,所以,Python寫類的時候,成員變數的初始化請務必寫到 __init__()函式裡
---------- 驗證圖片
first_person:
second_person: