python中的引用传递,可变对象,不可变对象,list注意点

Posted PilgrimHui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python中的引用传递,可变对象,不可变对象,list注意点相关的知识,希望对你有一定的参考价值。

python中的引用传递
首先必须理解的是,python中一切的传递都是引用(地址),无论是赋值还是函数调用,不存在值传递。

可变对象和不可变对象
python变量保存的是对象的引用,这个引用指向堆内存里的对象,在堆中分配的对象分为两类,一类是可变对象,一类是不可变对象。不可变对象的内容不可改变,保证了数据的不可修改(安全,防止出错),同时可以使得在多线程读取的时候不需要加锁。

不可变对象(变量指向的内存的中的值不能够被改变)
当更改该对象时,由于所指向的内存中的值不可改变,所以会把原来的值复制到新的空间,然后变量指向这个新的地址。python中数值类型(int和float),字符串str,元组tuple都是不可变对象。
下面以int类型为例简单介绍。

a = 1
print id(a)    //40133000L,整数1放在了地址为40133000L的内存中,a变量指向这个地址。
a += 1 
print id(a)    //40132976L,整数int不可改变,开辟新空间存放加1后的int,a指向这个新空间。

可变对象(变量指向的内存的中的值能够被改变)
当更改该对象时,所指向的内存中的值直接改变,没有发生复制行为。python中列表list,字典dict,集合set都是可变对象。下面以list类型为例简单介绍。

a = [1,2,3]
print id(a)    //44186120L。

a += [4,5]     //相当于调用了a.extend([4])
print id(a)    //44186120L,列表list可改变,直接改变指向的内存中的值,没开辟新空间。

a = a + [7,8]  //直接+和+=并不等价,使用+来操作list时,得到的是新的list,不指向原空间。
print id(a)    //44210632L

引用传递后的改变

a = [1,2,3]
b = a
b[0] = 2     //由于list是可变对象,改变b时候会导致a的改变,a和b都是[2,2,3]

s = ‘abc‘
s2 = s
s2 += ‘d‘   //由于str是不可变对象,s2是新建的对象,s2的修改不会影响s。s为‘abc‘,s2为‘abcd‘。

list注意点

a = [1,2,3]
b = a
a is b             //True,因为按引用传递,a和b存的地址(引用)是一样的,改变b相当于改变a。

b = a[:]
a is b            //False,想使用list的值却不想修改原list时可以使用[:]拷贝一份到新空间。

a =[ [0]*2 ]* 2   //以这种方式创建一个二维list,此时a为[[0,0],[0,0]]。
a[0] == a[1]      //True,这种创建方法的机制是复制list,所以2个list其实是同一个list。

a[0][0] = 1       //改变第一个list时第二个list也改变,此时a为[[1,0],[1,0]]。
a[0] += [1]       //改变第一个list时第二个list也改变,此时a为[[1,0,1],[1,0,1]]。
a[0] = [1,2]      //a[0]指向创建的新list[1,2]。此时a[1]不变,a为[[1,2],[1,0,1]]。





以上是关于python中的引用传递,可变对象,不可变对象,list注意点的主要内容,如果未能解决你的问题,请参考以下文章

python中的“引用”和C++的引用

python 引用

Python值传递和引用传递(详细分析)

Python中的可变不可变对象和赋值技巧序列解包

python 函数传递可变不可变对象

Python入门-5函数:05参数的传递-可变对象-不可变对象-浅拷贝和深拷贝-不可变对象含可变子对象