【问题标题】:Passing values by reference in multithread programming在多线程编程中通过引用传递值
【发布时间】:2013-12-19 13:40:09
【问题描述】:

我编写了一个程序,它使用线程模块创建一个线程,将 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

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

【问题讨论】:

    标签: python multithreading pass-by-reference


    【解决方案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】:

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

      class IntWrapper(object):
          val = 1
      
      def incr(obj)
          obj.val += 1
      

      这样就可以了

      【讨论】:

      • 如果多个线程会增加同一个计数器,它需要被锁保护。
      【解决方案3】:

      为此,您应该将变量初始化为 0

      在声明时也要更改你的变量名

      因为 var 是一个本身的关键字,所以最好使用另一个变量

      【讨论】:

      • var 不是 Python 中的关键字
      • @volcano 是的,但它是function
      • ----> 1 var NameError: name 'var' is not defined
      • @volcano 哎呀把它误认为vars
      猜你喜欢
      • 2017-06-28
      • 2020-05-03
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      • 2013-07-20
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      相关资源
      最近更新 更多