Python 传值和传址 copy/deepcopy
传值:被调函数局部变量改变不会影响主调函数局部变量
传址:被调函数局部变量改变会影响主调函数局部变量
Python参数传递方式:传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组则传值;如果是列表,字典则传址;
1. Python中的传址和传值
Python是不允许程序员选择采用传值还是传址的。Python参数传递采用传值和传址的一种综合。
如果函数收到的是一个可变对象(比如字典或者列表),就能修改对象的原始值(相当于传址)。如果函数收到的是一个不可变对象(比如数字、字符或者元组)(其实也是对象地址),就不能直接修改原始对象——相当于传值。
所以python的传值和传址是根据传入参数的类型来选择的
传值的参数类型:数字,字符串,元组(immutable)
传址的参数类型:列表,字典(mutable)
def f1(a):
a += 1
def f2(a):
a.append([2, 5]) a = 1
b = [1, 2]
f1(a)
f2(b)
print(a) #实际输出:1
print(b) #实际输出:[1, 2, [2, 5]]
因为a是数字类型,是传值的方式,a的值不变,输出为1。b的类型是列表,是传址的形式,b的值会改变,输出:[1, 2, [2, 5]]
2. copy和deepcopy
Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块。
(1). copy.copy 浅拷贝只拷贝父对象,不会拷贝对象内部的子对象(相当于只拷贝指向子对象的指针,不拷贝所指向的内容)。
(2). copy.deepcopy 深拷贝 拷贝对象及其子对象(拷贝子对象指针所指向的内容)
不止是函数里面,函数外面的引用也同样遵循这个规则:
a = 1
b = a
a = 2
print(a, b) #实际输出:2, 1
a = [1]
b = a
a[0] = 2
print(a, b) 实际输出:[2][2]
在python中,当运行上面的代码时,如果a是字典或者列表,b=a操作并不是新建一个b变量在把a赋值给b,而是新建一个b变量,把b的值指向a,相当于c语言里面新建一个指向a的指针。所以当a的值发生改变时,b的值会相应改变。
但是,当我们想新建一个与a的值相等的b变量,同时b的值与a的值没有关联时,要怎么做?这时就用到copy与deepcopy了
import copy
a = [1, 2, 3]
b = a
a.append(4)
print(a, b) #实际输出:[1, 2, 3, 4] [1, 2, 3, 4] a = [1, 2, 3]
b = copy.copy(a)
a.append(4)
print(a, b) #实际输出:[1, 2, 3, 4] [1, 2, 3]
这里用了copy来让b与a相等,后面如果修改了a的值,b的值并不会改变。看来copy已经可以实现我们上面的提到的需求了,那么deepcopy又有什么用?
如果我们遇到这种情况,copy就解决不了了
a = [1, [1, 2], 3]
b = copy.copy(a)
a[1].append(4)
print(a, b) #实际输出:[1, [1, 2, 4], 3] [1, [1, 2, 4], 3]
当列表或字典参数里面的值是列表或字典时,copy并不会复制参数里面的列表或字典,这时就要用到deepcopy了
a = [1, [1, 2], 3]
b = copy.deepcopy(a)
a[1].append(4)
print(a, b) #实际输出:[1, [1, 2, 4], 3] [1, [1, 2], 3]
Python 传值和传址 copy/deepcopy的更多相关文章
- Python的传值和传址与copy和deepcopy
1.传值和传址 传值就是传入一个参数的值,传址就是传入一个参数的地址,也就是内存的地址(相当于指针).他们的区别是如果函数里面对传入的参数重新赋值,函数外的全局变量是否相应改变,用传值传入的参数是不会 ...
- Java传值和传址
调用函数时,传的参数过去可能是传值,也可能是传址.如果是传值,函数内部的操作对参数的值没有影响:如果是传址,函数内部的操作是对参数指向的内存进行操作,会影响参数的值. Java到底是传值还是传址?用下 ...
- javascript的变量,传值和传址,参数之间关系
先把收获晾一下: 1.javascrip变量包含两种类型的值,一种为引用类型的值,一种是基本类型的值.引用类型包括:Array,Object,Function(可以这么理解,非基本类型的都是引用类型) ...
- 图解JS的传值与传址
//编程过程中经常会碰到传值,传址的问题!今天的主题就是关于传值.与传址. //先讲讲赋值操作 //下例是原始类型赋值操作 var a=1,b=a,a=2; console.log("a=& ...
- JAVA传值与传址
要了解JAVA中的传值与传址问题,必要先要了解JVA中的栈内存和堆内存,>>>>点些查看<<<<昨天写的学习记录 栈:基本数据类型.数据的引用变量,这两 ...
- javascript . 05 json的组成、for...in 遍历对象、简单数据类型与复杂数据类型的传值与传址、内置对象
对象字面量 JSON var obj = { aaa :999}; var json={"aaa":999,"bbb":888}; "kay&quo ...
- 工控随笔_18_西门子_WinCC的VBS脚本_07_变量作用域和传值、传址
在vbs脚本中也存在和其他编程语言一样的概念,那就是变量的作用域,变量的作用域决 定在什么范围内可以访问. 同样的在vbs脚本中对于变量也有一个生命周期, 变量的生命周期决定了变量的存续时间 这个主要 ...
- java方法中,传参是传值还是传址问题(对比C语言、C#和C++)
问题引出: 编写一个简单的交换值的小程序,如果我们只是简单地定义一个交换函数接收两个数,在函数内部定义一个中间变量完成交换.那么当我们把a,b两个实参传给这个函数时,往往得不到预期的结果.这是为什么呢 ...
- js- 引用和复制(传值和传址)
js- 引用和复制(传值和传址) 好像一般很少人讲到js中的引用和复制,不过弄清楚这个概念可以帮助理解很多东西 先讲一下很基础的东西,看看js中几种数据类型分别传的什么引用:对象.数组.函数复制:数字 ...
随机推荐
- Easyui入门视频教程 第05集---Easyui复杂布局
目录 ----------------------- Easyui入门视频教程 第09集---登录完善 图标自定义 Easyui入门视频教程 第08集---登录实现 ajax button的使用 ...
- ios实例开发精品文章推荐(8.5)
IOS基础知识记录 IOS基础知识记录一 http://www.apkbus.com/android-131902-1-1.htmlIOS基础知识记录二 http://ww ...
- maven Missing artifact com.sun:tools:jar:1.5.0
转自:http://blog.csdn.net/caolaosanahnu/article/details/7918929 http://zuoshahao.com/work/others/missi ...
- Linux init进程学习 转
http://oss.org.cn/kernel-book/ch13/13.6.1.htm init进程的建立 Linux将要建立的第一个进程是init进程,建立该进程是以调用kernel_threa ...
- excel中的数据粘贴不全到plsql中,excel 粘贴后空白,Excel复制粘贴内容不全
http://zhidao.baidu.com/link?url=pHZQvfWJzI-lQjl4uP86q4GLcpYHu4o-fdjiYegJS0Cy5HEq5oz0YrUye3iHjmv5CJ3 ...
- Swift 基本运算符
前言 Swift 语言支持大部分标准 C 语言的运算符,并且改进了许多特性来使我们的代码更加规范,其中主要包含算数运算符.区间运算符.逻辑运算符.关系运算符.赋值运算符.自增自减运算符.溢出运算符等. ...
- Linux VFS数据结构
先说明一下,linux内核中各种数据结构也不停的在变,所以不同版本的内核各个数据结构的定义可能会差别很大,这一组关于linux 文件系统的文章中的代码都摘自linux-2.6.34.1. VFS依赖于 ...
- java udp 广播
原文链接: http://blog.csdn.net/yudajun/article/details/8477149 udp 是一种网络通信协议,不需要客户端和服务器端建立连接即可进行通讯功能.相对于 ...
- SharePoint 2013 Step by Step——使用自定义的List Template
Overview 对于企业员工来说,"扁平结构"的LIST是日常操作中经常使用到的,LIST的好处是方便数据的录入以及数据的整理分析,尤其是Quick Edit功能,可以实现快速编 ...
- Hive sql 查询数据库查询 top-n
数据库查询*分组排序取top n要求:按照课程分组,查找每个课程最高的两个成绩. 数据文件如下: 第一列no为学号,第二列course为课程,第三列score为分数 mysql> select ...