Python:threading.Thread,值是通过值还是引用传递的?

时间:2018-10-31 10:55:11

标签: python multithreading pass-by-reference pass-by-value

我将值i传递给th = threading.Thread(target=func, args=(i,)),并由th.start()立即启动线程。 因为这是在具有更改索引i的循环内执行的,所以我想知道线程中的i是否从创建线程起就保留了它的值,或者该线程是否在对i的引用上工作。在后一种情况下,该值不一定与创建th时的值相同。 值是通过引用传递还是通过值传递?

2 个答案:

答案 0 :(得分:0)

按值传递和按引用传递是两个有时会引起误解的术语,它们在每种语言中的含义并不总是相同的。我假设我们要了解这两个术语在C语言中的含义(其中引用将指针传递给变量)。

Python确实不是两者中的任何一个,我给您举一个我从文章中摘录的示例(所有内容都归功于原始作者,我将在文章的最后链接)

def spam(eggs):
    eggs.append(1)
    eggs = [2, 3]

ham = [0]
spam(ham)
print(ham)

调用spam时,hameggs都指向相同的值([0]),指向相同的对象。因此,当执行eggs.append (1)时,[0]变为[0,1]。听起来像是通过引用。

但是,当eggs = [2, 3]时,现在eggsham都应成为通过引用传递的新列表。但这并没有发生。现在eggs指向内存中包含[2,3]的列表,但是ham仍指向原始列表并附加1。那一点听起来更像是按值传递。

编辑

如上所述,如果在线程内部修改了线程的参数,则只要该参数是可变的,更改就可以在原始线程中看到。这样,例如,将列表传递给线程并向其附加内容将反映在调用者线程中。

但是,不能修改不可变的对象。如果您执行i += 1,则没有修改整数,因为整数在Python中是不可变的。您正在为i分配一个新整数,该整数的值比以前的整数大一个单位。 eggs = [2, 3]发生的事情是相同的。因此,在该特定示例中,更改将不会反映在原始线程中。

希望这会有所帮助!

这是我答应过的文章,它对问题有更好的解释。 http://stupidpythonideas.blogspot.com/2013/11/does-python-pass-by-value-or-by.html?m=1

答案 1 :(得分:0)

  

我会说,将可变对象传递给函数是通过引用进行调用。

不想这么说的不是您一个人,而是以这种方式限制了您与他人就Python程序实际工作方式进行交流的能力。

考虑以下Python片段:

a = [1, 2, 3]
b = a
foobar(a)
if not b is a:
    print('Impossible!')

如果Python是一种“按引用传递”编程语言,那么foobar(a)调用可能会通过更改局部变量Impossible!来引用一些不同的变量,从而使该程序打印a。对象。

但是,Python不执行引用传递。它只传递值,这意味着没有foobar的定义可以使该片段执行print调用。 foobar函数可以使局部变量a所引用的对象发生突变,但是它不能修改a本身。

请参见https://en.wikipedia.org/wiki/Evaluation_strategy