關於Python的面相物件程式設計

1120161903發表於2020-10-26

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:

 

 

 

 

相關文章