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]]。

原文地址:https://www.cnblogs.com/liaohuiqiang/p/9668303.html

时间: 2024-10-14 07:54:26

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

python中的引用

作为一个python初学者,今天被一个python列表和词典引用的问题折磨了很久,但其实了解了缘由也很简单,记录在此备忘. 首先背书python中的引用对象问题: 1. python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方式.实际上,这种方式相当于传值和传引用的一种综合.如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象.如果函数收到的是一个不可变对象(比如数字.字符或者元组)的引用,就不能

(转载)理解Java中的引用传递和值传递

关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习和分析一下,着急可以先看最后的结论. 1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型.基本类型的变量保存原始值,即它代表的值就是数值本身:而引用类型的变量保存引用值,"引用值"指向内存空间的地址,代表了某

Java中没有引用传递只有值传递(在函数中)

◆传参的问题 引用类型(在函数调用中)的传参问题,是一个相当扯的问题.有些书上说是传值,有些书上说是传引用.搞得Java程序员都快成神经分裂了.所以,我们最后来谈一下“引用类型参数传递”的问题. 如下例子,假设现在要把刚才创建的那一坨字符串打印出来,我们会使用如下语句: StringBuffer str = new StringBuffer(); System.out.println(str); //这个语句又是什么意思捏?这时候就两说了. 第一种理解:可以认为传进函数的是str这个指针,指针说

VB6中的引用传递 与 VB.NET中的引用传递的区别

首先注意一点,在VB6中缺省参数传递的方式是:引用传递,而在VB.NET中缺省参数传递的方式是:值传递. 然后我们看下面VB6中的引用传递与VB.NET中的引用传递的对比. VB6中的引用传递 Private Sub CommandButton1_Click() ChangeName CommandButton1.caption End Sub Private Sub ChangeName(caption As String) caption = "NameHasBeenChanged!&quo

关于java中是引用传递还是值传递的问题!!!经常在笔试中遇到,今天终于弄明白了!

关于JAVA中参数传递问题有两种,一种是按值传递(如果是基本类型),另一种是按引用传递(如果是對象).首先以两个例子开始:1)public class Test2 { public static void main (String [] args) { StringBuffer a = new StringBuffer ("A"); StringBuffer b = new StringBuffer ("B"); operate (a,b); System.out.

python中的值传递和引用传递

Python中的变量是没有类型的,我们可以把它看做一个(*void)类型的指针,变量是可以指向任何对象的,而对象才是有类型的. Python中的对象有可变对象(number,string,tuple等)和不可变对象之分(list,dict等). 值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本.值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函

Python如何通过引用传递变量?

""" # 1 Python的函数参数传递 这里记住的是类型是属于对象的,而不是变量. 而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象.在python中,strings, tuples, 和numbers是不可更改的对象,而 list, dict, set 等则是可以修改的对象.(这就是这个问题的重点) 当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了. 所以第一个例子里函数把引用指向了一个不可变

Python参数传递(引用传递和值传递)

参考:https://blog.csdn.net/icessunt/article/details/80919188 python中的函数参数既支持按值调用,也支持按引用调用. python中的变量是对象引用: 变量存储的值是内存地址.当函数被调用的时候,解释器会查看传入的变量(内存地址)指的那个指的类型,如果是一个可变类型的值,就按照引用传递变量:如果是一个非可变类型的值,就考虑按照值传递变量. 可变类型:字典dict,列表list,集合set 不可变类型:字符串srt,整数int,元组tup

C#中的引用传递、值传递

  先来说下C#中的数据类型.分值类型和引用类型两大类. 值类型:直接存储数据的值,保存在内存中的stack(堆栈)中 引用类型:存储对值的引用,实际上存储的就是一个内存的地址.引用类型的保存分成两块,实际值保存在托管堆(heap)中.实际值的内存地址保存在stack中 当使用引用类型时先找到stack中的地址,再找到heap中的实际值. 也就是说保存引用类型时要用到stack和heap,但使用引用类型时我们实际上只用到stack中的值,然后通过这个值间接的访问heap中的值 C#预定义的简单类