python中的数据存储认识
python引用正确的理解方式
python中是不允许程序员直接选择是值传递还是地址传递(传递副本还是传递原本)。python中可以说只有一种传递参数的方式,那就是引用传递。只不过基于对象的不同,大致又可以分为不可变类型的引用传递和可变类型的引用传递。可变类型的引用可以有多个,但是储存信息的地址只有一个,所以当通过多个应用中的某个引用对存储内容进行修改时,其实都是对一个地址修改,所以会呈现出所有引用都变化的效果。不可变类型的引用只有一个,当你尝试在函数中改变这个变量的值时(即例如 变量名 = 新的值),python会新建一个变量引用用来指向这个新的值(使用id函数比较两个地址会返回False),两个对象虽然名字一样,但是它们两个是没有任何关系的,所以呈现出的效果就是原来的不可变对象不变。
可变类型(mutable):列表,字典
不可变类型(unmutable):数字,字符串,元组
这里的可变不可变,是指内存中的那块内容(value)是否可以被改变
进一步举例说明
python中的del函数的作用是删除一个对象的某个引用,而python的回收机制是当指向某对象引用为0时就将该对象回收。所以del在操作只有一个引用的对象时类似于直接删除对象的效果。
下面的代码为举例使用del函数删除a_list列表中的是三倍数的元素时出现的删除不了的状况。
def change(a_list_change): for data in a_list_change: if data % 3 == 0: del data a_list = [1, 3, 5, 7, 9, 11, 13, 15] change(a_list) print(a_list)
输出的结果为[1, 3, 5, 7, 9, 11, 13, 15]。原因在于del只删除了for循环迭代中产生的指向a_list_change元素的data引用,所以a_list的元素并不会被删除。
将其中的语句del data 改为a_list_change.remove(data)后的代码如下。
def change(a_list_change): for data in a_list_change: if data % 3 == 0: a_list_change.remove(data) a_list = [1, 3, 5, 7, 9, 11, 13, 15] change(a_list) print(a_list)
此时输出的结果为[1, 5, 7, 11, 13],可见已经把是三倍数的数字删除了。
此时如果是c语言的思维方式就无法解释这种删除引用的现象了。
顺便:python是一种足够智能的编程语言,当不可变类型int足够小,而且有多个引用指向它的时候,比较他们的id地址,会出现相同的情况,因为python为了节省内存,会出现这样的情况,但是不会影响用户的使用。