python引用传递还是值传递,以及copy和deepcopy的区别(转)

引用文章地址:http://www.cnblogs.com/loleina/p/5276918.html

引用文章地址:http://www.cnblogs.com/buptldf/articles/4976561.html

传参时引用传递和值传递的区别

引用传递:被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
值传递:被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

python中是如何传参的

python中的一切事物皆为对象,并且规定参数的传递都是对象的引用。可能这样说听起来比较难懂。参考下面一段引用:

  1. Python不允许程序员选择采用传值还是传 引用。Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典 或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能 直接修改原始对象——相当于通过“传值”来传递对象。
  2. 当人们复制列表或字典时,就复制了对象列表的引用同,如果改变引用的值,则修改了原始的参数。
  3. 为了简化内存管理,Python通过引用计数 机制实现自动垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相 应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。

多说无益,直接上例子

def test(b):
    print 'test before:%d,%d' % (b,id(b))
    b = b + 10
    print 'test after:%d,%d' % (b,id(b))

if __name__ == '__main__':
    a = 10
    print 'main before:%d,%d' % (a,id(a))
    test(a)
    print 'main after:%d,%d' % (a,id(a))

运行结果

main before:10,35422448
test before:10,35422448
test after:20,35422208
main after:10,35422448

图示


1.jpg

id函数可以获得对象的内存地址.很明显从上面例子可以看出,将a变量作为参数传递给了test函数,传递了a的一个引用,把a的地址传递过去了,所以在函数内获取的变量b的地址跟变量a的地址是一样的,但是在函数内,对b进行赋值运算,b的值从10变成了20,实际上10和20所占的内存空间都还是存在的,赋值运算后,b指向20所在的内存。而a仍然指向10所在的内存,所以后面打印a,其值还是10.

那python函数传参就是传引用?然后传参的值在被调函数内被修改也不影响主调函数的实参变量的值?

答案是否定的,正如上面所说的,当传递的参数是列表或者字典这种可变对象时,将直接对实参进行修改,让我们来看个例子

def test(b):
    print 'test before:%d,%d' % (b[0],id(b[0]))
    b[0] = b[0] + 10
    print 'test after:%d,%d' % (b[0],id(b[0]))

if __name__ == '__main__':
    a = [10]
    print 'main before:%d,%d' % (a[0],id(a[0]))
    test(a)
    print 'main after:%d,%d' % (a[0],id(a[0]))

运行结果

main before:10,35422448
test before:10,35422448
test after:20,35422208
main after:20,35422208

图示


2.jpg

结论

Python参数传递采用的是“传对象引用”的方式。 这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值'来传递对象。

copy 浅拷贝 只复制父对象,对象的内部的子对象依然是引用。

该怎么理解这句话,直接上例子

import copy

a = [1,2,3,[1,2,3]]

b = copy.copy(a)

a,b
Out[4]: ([1, 2, 3, [1, 2, 3]], [1, 2, 3, [1, 2, 3]])

a[3].append(4)
a,b
Out[8]: ([1, 2, 3, [1, 2, 3, 4]], [1, 2, 3, [1, 2, 3, 4]])

a.append(5)
a,b
Out[11]: ([1, 2, 3, [1, 2, 3, 4], 5], [1, 2, 3, [1, 2, 3, 4]])

id(a),id(b)
Out[19]: (204294024L, 204380424L)

id(a[3]),id(b[3])
Out[18]: (204294856L, 204294856L)

b是a的浅拷贝对象,对a列表添加一个值时,b列表没有变化。当对a列表内的一个子列表添加一个值时,b列表也发生了同样的改变。由他们的地址也可以看出,a,b是存储在不同位置的两个列表,但是a[3]和b[3]指向的是同一个列表。由此可以得出, 浅拷贝时,拷贝的内部子对象是一个引用,不是真正意义上的拷贝。

deepcopy才是真正意义上的拷贝

a = [1,2,3,[1,2,3]]

b = copy.deepcopy(a)

a[3].append(4)

a,b
Out[15]: ([1, 2, 3, [1, 2, 3, 4]], [1, 2, 3, [1, 2, 3]])

id(a[3]),id(b[3])
Out[16]: (204293768L, 204294600L)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 第5章 函数和函数式编程 5.1 引言函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数...
    VIVAFT阅读 943评论 0 5
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,521评论 0 5
  • http://python.jobbole.com/85231/ 关于专业技能写完项目接着写写一名3年工作经验的J...
    燕京博士阅读 7,545评论 1 118
  • 原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执...
    小猪啊呜阅读 4,583评论 1 19
  • 很多时候我们都犯者同样的错误 并且知道是犯错 依然停不下来 这是为什么
    儿子娃娃Erick阅读 118评论 0 0