在多线程编程中通过引用传递值

时间:2013-12-03 13:12:07

标签: python multithreading pass-by-reference

我编写了一个程序,它使用线程模块创建一个向先前定义的变量添加1的线程,但是,一旦程序终止,变量的值仍然相同。我试过这个:

from threading import Thread

def plus_one(var):
        return var + 1

var = 0

print var

my_adder = Thread(target = plus_one, args = (var, ))
var = my_adder.start()
my_adder.join()

print var

但它不起作用......我该怎么办?我已经搜索了一些信息,但这一切都让人很困惑......!

3 个答案:

答案 0 :(得分:1)

Python仅通过引用传递对象,标量值通过值传递。那么,如果你定义一个类

class IntWrapper(object):
    val = 1

def incr(obj)
    obj.val += 1

那将有效

答案 1 :(得分:1)

Python“变量”

在python中,你没有'变量',你不能'通过引用传递'或'按值传递'。你有'名字',它被绑定到内存中的值。这些值可以更改,或者名称可以更改。例如:

>>> x = 21
>>> y = x
>>> y
21

>>> x = 100
>>> y
21

创建函数时,任何值更改的名称都会被视为新名称,并且不会指向外部名称:

>>> x = 21
>>> def do(a):
        x = a + 100  # x here is a new local name, since you've assigned to it.
>>> do(x)
>>> x
21

但是,如果您所做的只是读取名称,那么python将允许您从父“范围”中读取变量:

>>> x = 21
>>> def p():
        print (x)

>>> p()
21

这是您的代码的第一个问题。这样做的方法是使用全局定义的名称,并告诉函数使用该全局名称:

>>> x = 21
>>> def do():
        global x
        x = 41
>>> do()
>>> x
41

(在python 3中,您可以使用nonlocal而不是global来访问父作用域中的非全局名称。

当您返回一个值时,您需要在与其定义的范围相同的范围内为该值指定名称。

可变和不可变的名称:

如果将名称绑定到数字,元组或字符串之类的值,则值为immutable。你无法改变它。因此,每当您说x = 1然后x = 21时,您不会更改x的值,而是重新绑定x以指向新值。这就是y = x示例y没有改变的原因。它仍然受旧价值的束缚。值没有改变,但x现在指向一个新值。

然而,并非python中的所有内容都是不可变的。列表,词组,对象等不是不可变的。所以:

>>> x = [100]
>>> def do(l):
        l[0] = 50
>>> do(x)
>>> x
[50]

此外:

>>> x = [21]
>>> y = x
>>> x[0] = 50
>>> y
[50]

如果你真的需要,这可以用来'通过引用传递值'。但是,如果你滥用它,通常是一个好的迹象,不知何故代码的结构是错误的。

线程和变量访问

您正在做的是返回一个新值,但不会将其分配到任何地方。线程.start()方法不起作用。原因是,如果它确实如此,那么你将阻塞当前线程(实际上将名称绑定到新值),等待返回新值以将其设置为的那个,这将错过线程点

您可以使用上述方法解决此问题。

你真正需要注意的一件事是,如果多个线程试图同时访问相同的值,那么从多个线程访问的变量可能相当可怕,事情表现不正常。

这是一篇关于'锁'的非常好的文章,以及如何安全地使用线程。

http://effbot.org/zone/thread-synchronization.htm

享受!

答案 2 :(得分:0)

为此你应该将你的变量初始化为0

在声明时也会更改您的变量名称

因为var是一个自己的关键字所以最好使用另一个变量