为什么使用python去讲解这个概念?
讲解这个概念必须举例说明。但是在JAVA中这个概念和引用调用和传值调用一起,互相交替出现在不同的情况,变得非常的难以理解。
而python语言中,所有的变量都是引用变量。不存在值变量。故使用python可以较为存粹的阐述 可变对象和不可变对象的区别而不用涉及引用调用和传值调用问题。
阅读下文之前,默认你学习过python基本的语法,知道列表、元组、字符串等等基本python内置数据结构。
python基本存储概念
在python程序中,真实的变量数据存放在一个数据地址的位置。
而变量本身存放的永远是这个数据变量的地址。
也就是说,python中只存在引用变量。
在python中使用id()内置函数获得一个变量存储的数据的真实地址。
举例如下:命令行模式下执行两行代码。返回值在第三行:
>>a=6
>>id(a)
1488730448
这里返回的1488730448就是中存储的数据的地址。
什么是可变对象,什么是不可变对象?
可变对象就是,可以变化的对象。
这个可以变和不可以变是针对同一内存地址来说的。
当你声明一个变量并赋值的时候,将自动为其分配一个内存地址,如果是可变对象。可以在内存地址不改变的情况下,更改自己的值。如果是不可变对象,则不能更改自己的值。
举个例子,数字常量就是不可变对象。
很多人一头雾水,什么意思?难道还存在不可以变化的对象?数字常量不可以变化,那么我平时是怎么多次赋值的?
其实编程语言替你实现了一步。在你为一个不可变对象赋新值的时候,实际上是开辟另一个空间去存储这个新值,然后编程语言自动的将新的值赋给这个变量。
例子如下。
>>> pre=3
>>> id(pre)
1488730400
>>> pre=4
>>> id(pre)
1488730416
>>>
明白了这一点,那么举例一个可变对象就非常好理解了。
比如在python中列表是可变对象。
>>> pre=[1,2]
>>> id(pre)
57851176
>>> pre=[1,2,3]
>>> id(pre)
57851816
不可变对象的唯一性
其实直接上代码就能理解这个概念
>>> a1=3
>>> a2=3
>>> id(a1),id(a2)
(1488730400, 1488730400)
不可变对象如果开辟时在内存中已经存在一个同值的不可变对象,那么将共享同一个不可变对象。
But why?
其实这个概念本身非常好理解。相信大家都已经懂了。
但是为什么编程语言中为什么要设计不可变对象这种东西呢?
存在即合理。
如果这个概念没道理相信也不会有这么多语言都设计了这样一组概念了。
相对于可变对象,不可变对象有很多优势:
1).不可变对象可以提高传输的效率和安全性。如果你知道一个对象是不可变的,那么需要拷贝这个对象的内容时,就不用复制它的本身而只是复制它的地址,复制地址(通常一个指针的大小)需要很小的内存效率也很高。对于同时引用这个“ABC”的其他变量也不会造成影响。
2).不可变对象对于多线程是安全的,因为在多线程同时进行的情况下,一个可变对象的值很可能被其他进程改变,这样会造成不可预期的结果,而使用不可变对象就可以避免这种情况。
第一点主要是针对java这样的传值和引用调用都存在的语言。在python中根本不存在传值的问题。而第二点才是设计这个概念的关键原因。其实以上两点是主要原因,但原因并不仅限于此。比如hash时使用不可变对象将造成巨大风险。
正是为了安全、效率的考虑。大部分的编程都设计了不可变对象这一概念。