2011-11-18 78 views
6

看看下面的代码我以为Python通过引用传递了一切吗?

#module functions.py 
def foo(input, new_val): 
    input = new_val 

#module main.py 
input = 5 
functions.foo(input, 10) 

print input 

我想输入现在是10.这是为什么不是这样?

+0

通过在函数foo的定义中调用局部变量“input”,您可能会迷惑自己。另外,斯文在答案中说。 – phkahler

+6

无论你在哪里阅读过,Python都会通过引用传递所有内容,它们是错误的。 –

回答

13

一切都按值传递,但该值是对原始对象的引用。如果修改对象,则更改对于调用者可见,但不能重新分配名称。而且,许多对象是不可变的(整数,浮点数,字符串,元组)。

+8

“[习惯Python](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables)”很好地说明了这种现象。 –

+1

Python不是按值或按引用调用,请参阅我的答案了解详细信息。 –

+1

@skyhisi:除了使用非标准术语“按对象调用”之外,您的答案与我的答案基本相同,我故意避免使用非标准术语,因为它没有解释任何事情。 –

8

在foo中,您将当地名称input绑定到不同的对象(10)。在调用上下文中,名称input仍指5对象。

5

Python中的赋值不会就地修改对象。它重新命名一个名称,以便在input = new_val之后,本地变量input获得新值。

如果要修改“外” input,你必须把它包一个可变的对象内,如一个元素的列表:

def foo(input, new_val): 
    input[0] = new_val 

foo([input]) 

Python不通过就按引用就像C++引用传递的工作方式一样。在这种情况下,至少,它更仿佛每个参数是在C/C++的指针:

// effectively a no-op! 
void foo(object *input, object *new_val) 
{ 
    input = new_val; 
} 
+0

感谢大家的回答......你提出的这个方法看起来几乎就像一个黑客,这是标准程序吗?有没有其他方法可以修改更pythonic的不可变类型? (我想'修改不可变类型'回答我自己的问题,但我会问无论如何...) – Ferguzz

+0

@Ferguzz你不能通过定义修改不可变对象。但那真的是你要问的吗?到目前为止,甚至还没有提到不可变对象。 “var = ...”不修改任何对象或任何其他变量的事实与不变性无关。你不能让一个变量赋值改变另一个变量,就像你不能改变一个列表会影响另一个列表一样。 – delnan

+0

我指的是这个答案中的一行'将它包装在一个可变对象(如列表)中“。我试图问,有没有办法像我原来的帖子那样修改变量,而不这样做? – Ferguzz

3

Python是既不呼叫按值,或呼叫按引用,它是Call By Object

“参数被调用的共享传递,类似到 呼叫按值,除了自变量的对象 ,如果他们是可变的,只能改变。”

+1

不错的总结,但我仍然认为逐个对象与按值调用没有区别,所有“值”都是对象的句柄(〜=指针)。 – Kos

相关问题