Python中函数调用是传值还是传引用?

Python在调用函数的时候,究竟是传值还是传引用呢?
这个问题的答案无外乎这几种说法:传值,传引用,对于可变对象是传引用,不可变对象是传值。

  1. 传引用

先看下面这个例子:

>>> def foo(n):
...         print id(n)
...         n = 3
...         print id(n)
>>> n = 2
>>> id(n)
31030000L
>>> foo(n)
31030000L
31029976L
>>> n
2
>>> id(n)
31030000L

foo中两次输出不相等可以看出,传引用说法并不成立。

  1. 传值

来看下面的例子:

>>> def foo(n):
...        print n
...        n.append(3)
...        print n
>>> n = [1, 2, 4, 8]
>>> foo(n)
[1, 2, 4, 8]
[1, 2, 4, 8, 3]
>>> n
[1, 2, 4, 8, 3]

按传值的说法,一个值传进来,在函数内改动并不会影响变量本身的值,上面例子中n变量本身的值也被改变了,说明传值的说法也不对。

3.可变对象传引用,不可变对象传值

相比上面两种说法,这种说法似乎更靠谱,传播也更为广泛,那它到底对不对呢?

>>> def foo(n):
...        print id(n)
...        n = ['1', '2', '3']
...        print id(n)
...        print n
>>> n = [1,2,3,4,5,6]
>>> id(n)
35637576
>>> foo(n)
35637576
35916168
['1', '2', '3']
>>> n
[1, 2, 3, 4, 5, 6]

按照可变对象传引用的说法,上面list类型是可变对象,应该传引用,这foo方法中两次调用id应该输出一样的值,更改的结果也应该影响到外部变量,但结果显然不是这样的,这说明,这种说法也是不正确的。

那么Python传值的方法到底是什么样呢?其实Python中的函数参数所遵循的是传对象(call by object),或者叫做穿对象的引用(call by object reference)。在调用函数时,将变量整个对象传入,对于可变对象的修改,在函数内外均可见;而对于不可变对象,因为其并不能真正意义上被赋值,修改是通过生成新的对象来实现的。

下面来一个有趣的例子作为结尾:

>>> def bar(a = []):
...        print id(a)
...        a.append(7)
...        print a
>>> for _ in range(5):
...        bar()
#结果输出请自己动手实践,原因应该不难理解
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • http://python.jobbole.com/85231/ 关于专业技能写完项目接着写写一名3年工作经验的J...
    燕京博士阅读 7,676评论 1 118
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,334评论 9 118
  • 故事里走过匆匆时光,那些散去的记忆,仍旧遗留在心中,成为一道最亮的风景。空徘徊,断惆怅,那时的那时,让记忆定格在属...
    大芝哥阅读 308评论 0 0
  • 因生活习惯,我对“青梅”了解不多,去年的夏末,朋友送给了我一瓶从化的青梅酒,还特意提醒,要冰镇后再喝。 我向来对酒...
    田舍君阅读 1,630评论 6 16
  • 准备纸笔水彩,打开手机播放音乐,循环播。拿起笔准备常试画葡萄,前一次画多肉植物突发奇想画葡萄,来了兴致,今天就试吧...
    兰花草的梦阅读 236评论 5 5