在Python中可以不使用指针而传递引用作为参数吗?
因为Python没有指针,我在想怎么才能把一个对象的引用传递给一个函数,而不是复制整个对象。这个例子有点牵强,但假设我写了一个这样的函数:
def some_function(x):
c = x/2 + 47
return c
y = 4
z = 12
print some_function(y)
print some_function(z)
根据我的理解,当我调用some_function(y)时,Python会分配新的空间来存储这个参数的值,然后在函数返回c后就会删除这些数据,因为这些数据不再需要。既然我在some_function里面并没有改变这个参数,那我怎么才能在函数内部简单地引用y,而不是在传递时复制y呢?在这种情况下影响不大,但如果y非常大(比如一个巨大的矩阵),复制它可能会消耗大量的时间和空间。
2 个回答
在Python中,参数总是以“引用”的方式传递。
Python中的参数工作方式以及文档中对它们的解释,可能会让刚接触这门语言的人感到困惑,尤其是如果你之前学过其他语言,那些语言允许你选择“值传递”和“引用传递”。
在Python中,“引用”其实就是一个指针,带有一些额外的信息,帮助垃圾回收器完成工作。而每个变量和每个参数始终都是“引用”。
所以,Python内部实际上是将一个“指针”传递给每个参数。你可以通过这个例子轻松看出这一点:
>>> def f(L):
... L.append(3)
...
>>> X = []
>>> f(X)
>>> X
[3]
变量X指向一个列表,而参数L是这个列表“指针”的一个副本,而不是列表本身的副本。
需要注意的是,这和C++中的“引用传递”(使用&
修饰符)或Pascal中的var
修饰符并不相同。
很遗憾,你的理解完全错误。Python 并不是在复制值,也不是为新值分配空间。它传递的是一个值,这个值实际上是指向对象的引用。如果你修改了这个对象(而不是重新绑定它的名字),那么原来的对象也会被修改。
编辑
我希望你不要再担心内存分配的问题:Python 不是 C++,大多数时候你根本不需要考虑内存。
用列表来演示重新绑定会更简单:
def my_func(foo):
foo.append(3) # now the source list also has the number 3
foo = [3] # we've re-bound 'foo' to something else, severing the relationship
foo.append(4) # the source list is unaffected
return foo
original = [1, 2]
new = my_func(original)
print original # [1, 2, 3]
print new # [3, 4]
如果你把思考方式转变为关注名字而不是变量,可能会更有帮助:在函数内部,名字 "foo" 一开始是指向原始列表的引用,但后来我们把这个名字改成指向一个新的、不同的列表。