不可變類型與可變類型:更深入的理解
不可變類型和可變類型之間的差異可能會引起混亂,尤其是當它出現時某些繼承自不可變類型的類別。
不可變型別:設計不變
在 Python 中,不可變型別是指其值無法就地修改的物件。不可變物件一旦創建,就保持不變;任何修改它的嘗試都會產生一個新物件。例如,浮點物件是不可變的,這意味著它不能直接更改。
子類化不可變類型:創建可變性的幻象
但是,可以創建看似可變的不可變類型的子類。這是透過重寫 __new__ 方法來實現的。例如,RoundFloat 類別是float 的子類,它將其值四捨五入到小數點後兩位:
class RoundFloat(float): def __new__(cls, val): return float.__new__(cls, round(val, 2))
雖然此程式碼定義了一個繼承自float 的新類,但RoundFloat 物件仍然是不可變的。這是因為 __new__ 方法只是創建一個具有捨入值的新浮點對象,並且它不會更改原始浮點對象。
可變類型:內部變更
相反,可變類型允許直接修改它們的值。定義方法的類別可以被認為是可變的。例如,SortedKeyDict 類別繼承自 dict 並定義 example() 方法:
class SortedKeyDict_a(dict): def example(self): return self.keys()
該類別允許在提供的方法中修改其值。然而,值得注意的是,SortedKeyDict 類別本身仍然是不可變的。它的值可以更改,但底層實例保持不變。
在實踐中理解可變性
為了更好地理解不可變類型和可變類型之間的區別,請考慮以下內容設想。使用 __new__ 將集合 d 傳遞給 SortedKeyDict 類別會引發錯誤,而使用 __new__ 將其傳遞給 RoundFloat 類別則不會。
d = (('zheng-cai', 67), ('hui-jun', 68),('xin-yi', 2)) SortedKeyDict.__new__(cls, d) # Error raised RoundFloat.__new__(cls, 12) # No error
這說明 SortedKeyDict 是可變的,而 RoundFloat 是不可變的。由於 SortedKeyDict 是可變的,因此可以在其方法中就地修改它。相較之下,RoundFloat 是不可變的,因此將其傳遞給 __new__ 不會修改原始物件。
以上是Python 中的不可變型別與可變型別:子類化何時會破壞不可變性?的詳細內容。更多資訊請關注PHP中文網其他相關文章!