匿名用户
1级
2017-10-26 回答
这个问题的答案无外乎这几种说法:传值,传引用,对于可变对象是传引用,不可变对象是传值。
传引用
先看下面这个例子:
>>> 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中两次输出不相等可以看出,传引用说法并不成立。
传值
来看下面的例子:
>>> 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()
#结果输出请自己动手实践,原因应该不难理解