# 不可变对象(immutable)的意义

# 不可变对象(immutable)的意义

mutable和immutable是Python层面的概念,这些Python的数据结构,在C的层面都是可以被“改变”的。也就是如果你写一个C extension,那这些所谓immutable的东西你都可以随便改。所以接下来我们把讨论范围限制在纯Python。

在刚开始了解immutable的时候,肯定会有人有疑惑——为什么要引入这个概念?在Python中,把int,str,tuple之类的数据结构设计成immutable,有什么意义?

任何语言层面上的设计,最终都是要对用户有帮助;所谓的immutable,本质上就是让你可以one thing less to worry about。你可以确认你使用的这个数据结构,它永远都不会变。

我们知道,在Python中,所有的变量本质上都是一个指针,指向真正的数据结构。如果没有immutable,那就意味着当我做 a = 1​ 之后,我在未来的编程过程中,都要小心这个 1​ 被修改了,a​ 它不是 1​ 了。字符串也是一个道理,当我做了 s = "abc"​ 之后,如果 str​ 不是immutable,那 s​ 保存的字符串也可能随时被其他程序更改。通过immutable的设计,就是让你放心,变量里保存的这种数据是不会变的。

提到immutable就还应该提起一下Python中机会最常用的数据结构之一-字典。大家知道,不是所有的数据都可以当字典的key的,这是因为字典的key必须要保证hash是始终不变的,否则字典就会出问题。在这种情况下,immutable的数据就有天然的优势——我这数据都不会变,我的hash肯定也不变啊!

immutable的出现还带来了一些优化上的可能性。比如说,当两个变量都保存 1​ 这个整数的时候,我们是应该让它们指向同一个整数数据,还是不同的呢?如果Python的整型不是immutable的,那就在编译的时候必须设计成指向不同的,否则两个变量就会互相影响。这样就导致了在一个程序中,可能需要建立大量的整型和字符串数据,占用内存也消耗计算。而当数据是immutable的时候,无论有多少个变量保存 1​ 这个整数,我们都可以让这些变量指向同一个1​ ,因为我们知道它不会变嘛!这就省了内存,提升性能了。而Python也确实是这么优化的。具体的优化细节我们未来有机会再说。

当然,immutable本身也会出现一些坑(所有的feature背后都藏着可能遇到的bug),比如最经典的,immutable并不一定不变,它只是本身不变,它里面包含的数据是可能变的。你可以把一个list放到tuple里,tuple依然是immutable,保存的list不会换成其他的list,但是这个list可能内部会变,就导致tuple包含的这个大的数据结构实际上是产生了变化的。

这个问题是Python的设计决定的,就像前面说的,所有的变量都是指针,tuple里存的也是指针,你只能保证指的永远是某个东西,而不能保证指着的这个东西不发生变化。