Python 修改函数中的给定列表

Python 修改函数中的给定列表,python,function,multiprocessing,Python,Function,Multiprocessing,我想给传递给函数的列表分配新值。在get\u p\u values的情况下,它可以正常工作,但在“read\u occulation”时则不行(我得到的输出是:[[0]、[0]、[0]、[0]、[0]],而不是[[1,2,3]、[1,2,3]、[1,2,3]) 注意,我将列表矩阵[index]传递给函数read\u occulation的原因是我需要使用Lock的acquire()和release() #!/usr/bin/python # Filename: untitled.py # enc

我想给传递给函数的列表分配新值。在
get\u p\u values
的情况下,它可以正常工作,但在“read\u occulation”时则不行(我得到的输出是:[[0]、[0]、[0]、[0]、[0]],而不是[[1,2,3]、[1,2,3]、[1,2,3])

注意,我将列表
矩阵[index]
传递给函数
read\u occulation
的原因是我需要使用
Lock
acquire()
release()

#!/usr/bin/python
# Filename: untitled.py
# encoding: utf-8

from __future__ import division
from multiprocessing import Process

def read_occupation( matrix ):
    matrix = [ [1,2,3] ]

def get_p_values( p):
    for index,value in enumerate( xrange(0,3,1)):
        p[index] = value

def main():
    p         = [ [0] ] * 3 
    matrix    = [ [0] ] * 4

    get_p_values( p )
    print p

    for index in xrange(0,3,2):
            p1 = Process( target=read_occupation, args=( matrix[ index     ] ) )
            p2 = Process( target=read_occupation, args=( matrix[ index + 1 ] ) )

            p1.start()
            p2.start()

            p1.join()
            p2.join()

    print matrix


if __name__ == '__main__':
    main()

它不起作用的原因有很多

首先,在函数
read_occulation
中,您正在更改局部变量的绑定。原始对象保持不变。相反,在
get\u p\u values
中,您正在修改对象(
[]
操作符调用对象的
\uuuuuuu setitem\uuuu
函数来更改内部表示)。在这种情况下,更好的办法是使用适当的对象

如果要在
read_occulation
中更改列表的全部内容,可以使用列表拼接运算符指定给整个列表:

def read_occupation(matrix):
    matrix[:] = [ [1, 2, 3] ]
顺便说一句,如果调用函数
read\u occulation
,调用方可能希望它不会更改其参数。您可能应该将其重命名为
update\u occulation
或类似的名称

其次,当您通过乘法创建变量时,您会得到一个
列表,其中每个索引都包含对同一项的引用。代码
p=[[0]]*3
相当于:

>>> l = [0]          # Naming the list for more clarity
>>> p = [ l, l, l ]  # Each index points to the same list `l`
第三,
Process
类期望其
args
参数有一个
tuple
(或者实际上是遵循iterable协议的对象)。您传递的不是一个元组,而是一个恰好是一个
int
list
(这就是您得到
TypeError
异常的原因)。您需要使用以下语法来传递元组

# Please note the comma after the closing bracket, it is important
p1 = Process( target=read_occupation, args=( matrix[ index     ], ) )

# In python, the syntax for a tuple is weird for tuple of size < 2
#  . tuple of 0 item:  ()
#  . tuple of 1 item:  (1,)
#  . tuple of 2 items: (1, 2)
#请注意结束括号后的逗号,它很重要
p1=进程(目标=读取占用,参数=(矩阵[索引],)
#在python中,对于大小小于2的元组,元组的语法很奇怪
#  . 0项的元组:()
#  . 1项的元组:(1,)
#  . 两项元组:(1,2)

第四,使用
multiprocessing.Process
,生成一个执行代码的新进程。您的代码中没有通信(我不知道是否有可能从这个过程返回到原始过程)。因此,原始代码中的变量未被修改。

此块具有误导性:

p         = [ [0] ] * 3 
matrix    = [ [0] ] * 4
尝试执行p[0]。追加(0),您将得到:

[[0, 0], [0, 0], [0, 0]]
因为[[0]]*3创建了一个包含三个对象的列表,所有对象都指向同一个列表


更糟糕的是:如果你修复了这个+sylvain所说的,我不确定你的程序是否会工作,因为p1和p2将尝试访问相同的列表。在使用之前,您应该仔细阅读
多处理
文档。这是一个非常棘手的库,充满了令人讨厌的陷阱。

除了Sylvain所说的,当然它仍然不起作用,因为一个进程不能修改其父进程的变量。创建新流程时,将复制变量

您可以尝试以下示例

from multiprocessing import Process

def modify(idx, li):
    li[idx] = 'hello'

a = [0] * 3 

p = Process(target=modify, args=(1, a))
p.start()
p.join()
print a

modify(1, a)
print a
结果将是:

[0, 0, 0]
[0, 'hello', 0]
提供了一种跨多个进程共享Python列表的方法:

from __future__ import division
import multiprocessing as mp   

def read_occupation( matrix,i ):
    matrix[i]=[1,2,3]

def main():
    manager=mp.Manager()
    matrix=manager.list([ [0] ] * 4)

    for index in xrange(0,3,2):
        p1 = mp.Process( target=read_occupation, args=(matrix,index) )
        p2 = mp.Process( target=read_occupation, args=(matrix,index+1) )

        p1.start()
        p2.start()

        p1.join()
        p2.join()

    print matrix

if __name__ == '__main__':
    main()
屈服

[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]

您需要修复此处的缩进,以便我们能够理解代码。@Syivain,我尝试使用matrix.\uuuuuSetItem(切片(0),[1,2,3]),但也确实有效。@Syivain,我测试了您的建议,但无效,我得到以下错误:TypeError:“int”对象不支持项分配(ps,我使用的是python 2.7)@Eagle:只有当参数
矩阵
是一个
列表
时,它才会起作用。从您的错误来看,似乎您没有将
列表
传递给函数,而是将
int
传递给函数。对于“创建了一个新进程”,我的意思是当它从其父进程分叉时。我不知道它是否正确表达了我的意思,对不起:(感谢您的重播,但我的问题有解决方案吗?正如您所介绍的,没有…@Eagle提供了许多解决方案。您可以根据自己的需要修改易晃的代码。如果您不理解答案中的某些内容,请告诉我们。如果您真的想使用流程,我认为unutbu的解决方案可能足够好。我只想假设多进程解决方案可能比单进程解决方案慢得多,如果您想在子进程中执行的操作与您的
read\u accountry
一样简单。我想您可以看看该部分。@Yi Huang,这是一个简单的示例,我真正要做的是从文件中读取一些数据,这需要相同的时间(有时到1小时)