对象和变量
对象 = 内存空间和指向次数
变量 = type + id + value
什么是引用
引用在python中的语义应该是一种关系,变量和对象之间的关系,其实也就是指针指向某一块内存空间的关系。既然是变量和对象之间的关系,那么其实就意味着,对于一个对象来说,和不同的变量可能存在着多个“引用”关系。因为变量是无类型的,他想关联谁就可以指向谁,这也就牵扯到了一个“引用计数”的概念,python中的gc大体上就是使用这种原理在做的。
既然说到多个变量可以引用同一个对象,那么就不得不说一下,如果其中一个引用改变了值,会影响到其他指向这个对象的变量么?
>>> a = 2
>>> b = a
>>> a
2
>>> b
2
>>> b = 3
>>> a
2
>>> b
3
从上面的代码结果来看,答案应该是否定的。如果了解清楚变量和对象的语义就能对这个问题很容易做出判断,变量值的改变,就相当于指针变量内存空间内值的改变,也就是指向的对象换了一个,但其实之前所指向对象的内容是并没有收到影响的。
但是也有特例,比如列表,指向列表的变量通过索引访问的方式,可以直接改动列表在该索引处存储的值。这个时候,如果有两个变量同时引用一个列表对象,那么其中任何一个变量利用这种方式对列表的修改,都会影响到另外一个。
为了能够避免这种情况,可以对列表单独拷贝一份。两个变量互不干涉,而拷贝列表最直接的方式,莫过于“切片”操作了。
python遵循变量和对象分离的原则
什么叫变量和对象分离?对象通过赋值与对象建立关系
举个栗子
>>> a = 1
>>> id(a)
1833649808
>>> a = 'asd'
>>> id(a)
48500096
变量是a 对象分别是 1 和 ‘asd’
第一个语句中, 2是储存在内存中的一个整数对象,通过赋值 引用a 指向了 对象 1
第二个语句中,内存中建立了一个字符串对象‘asd’,通过赋值 将 引用a 指向了 ‘asd’,同时,对象1不在有引用指向它,它会被python的内存处理机制当垃圾回收,释放内存。
继续举栗子
>>> li = [1,2]
>>> l2 = li
>>> l2
[1, 2]
第一个语句中,开辟了一块内存空间存放一个列表,并在列表中添加两个元素 1,2 通过赋值 引用li指向 对象[1,2]
第二个语句中,引用l2 指向 引用 li ,由于指向了引用,通过引用直接指向了 对象[1,2]
所以第三句打印l2 时 直接打印的对象[1,2]
续上一个栗子
>>> l2.append(3)
>>> li
[1, 2, 3]
通过l2 这个变量 调用 list的方法,添加了一个元素3, 其实时通过 l2 这个变量找到了对应的 对象[1,2] , 由对象调用了append方法添加了元素 3
打印li 为什么也有元素3 呢? 前面说过,变量来l2 指向对象[1,2] 而 变量li 也指向了对象 [1,2] 也就是说 变量li 和 变量l2是在操作同一个对象,可以理解成 对象有两个别名分别叫li 和l2