不可变类型与可变类型:更深入的理解
不可变类型和可变类型之间的差异可能会引起混乱,尤其是当它出现时某些继承自不可变类型的类。
不可变类型:设计不变
在 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中文网其他相关文章!