我将值i传递给th = threading.Thread(target=func, args=(i,))
,并由th.start()
立即启动线程。
因为这是在具有更改索引i的循环内执行的,所以我想知道线程中的i是否从创建线程起就保留了它的值,或者该线程是否在对i的引用上工作。在后一种情况下,该值不一定与创建th时的值相同。
值是通过引用传递还是通过值传递?
答案 0 :(得分:0)
按值传递和按引用传递是两个有时会引起误解的术语,它们在每种语言中的含义并不总是相同的。我假设我们要了解这两个术语在C语言中的含义(其中引用将指针传递给变量)。
Python确实不是两者中的任何一个,我给您举一个我从文章中摘录的示例(所有内容都归功于原始作者,我将在文章的最后链接)
def spam(eggs):
eggs.append(1)
eggs = [2, 3]
ham = [0]
spam(ham)
print(ham)
调用spam
时,ham
和eggs
都指向相同的值([0]),指向相同的对象。因此,当执行eggs.append (1)
时,[0]变为[0,1]。听起来像是通过引用。
但是,当eggs = [2, 3]
时,现在eggs
和ham
都应成为通过引用传递的新列表。但这并没有发生。现在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
本身。