Python 3.x 使用+;=操作人员

Python 3.x 使用+;=操作人员,python-3.x,list,dictionary,python-multiprocessing,multiprocessing-manager,Python 3.x,List,Dictionary,Python Multiprocessing,Multiprocessing Manager,考虑以下python代码: 来自多处理导入进程的管理器 类MyClass(): 定义初始化(self,dic1,dic2): self.dic1=Manager().dict(dic1)#创建托管字典 self.dic2=Manager().dict(dic2)#创建托管字典 process1=进程(target=self.com,args=()) process2=Process(target=self.dictsumementwise,args=()) process1.start() pr

考虑以下python代码:

来自多处理导入进程的管理器 类MyClass(): 定义初始化(self,dic1,dic2): self.dic1=Manager().dict(dic1)#创建托管字典 self.dic2=Manager().dict(dic2)#创建托管字典 process1=进程(target=self.com,args=()) process2=Process(target=self.dictsumementwise,args=()) process1.start() process1.join() process2.start() process2.join() def过载(自): self.dic1['1'][0]+=1#未更新dic1 def DICTSUMENTWISE(自): a=自.dic2['1'] self.dic2['1']=[a[0]+1,a[1],a[2]]#dic2已更新 def main(): dic1={'1':[1,0,0]} dic2={'1':[1,0,0]} 结果=MyClass(dic1,dic2) 打印(result.dic1)#失败 打印(result.dic2)#成功 #绕过多处理环境 dic3={'1':[1,0,0]} dic3['1'][0]+=1 印刷(dic3)#成功 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': main() 在本例中,我创建了一个托管dict,其中包含一个列表作为
MyClass
的属性。目标是在多处理环境中增加此列表的某些元素,但某些方法不能有效地修改列表

方法1:
方法
重载运算符
+=
用于将列表中的一个元素增加1,但结果不会持久。dict未更新。
方法2:
dictsumementwise

此函数基于旧列表和要添加的值创建新的列表元素。然后将新列表分配给dict键。已成功修改dict。
健全性检查:在多处理环境之外
当在多处理环境之外使用
+=
时,
dic3
按预期进行修改

问题
1) 为什么
+=
在多处理环境中不修改列表元素?

2) 使用基于元素的方法来更新列表是可行的,但是很麻烦,有什么建议可以让列表更干净/更快吗?

我相信您遇到的问题与您创建它时使用的匿名
管理器
对象检测到字典
dic1
中的更改有关

使用
+=
运算符更改列表本身不会更改对列表的引用-它是相同的列表,只是其中的一个元素发生了更改(即存储在线程安全字典
dic1
键下的列表的第0个元素
'1'

使用
dic2
时,情况有所不同。使用以下行:

self.dic2['1'] = [a[0]+1, a[1], a[2]]
您可以有效地更新键
'1'
下存储的值。指定的值是一个全新的列表。它由存储为同一键下的上一个值的列表元素组成,但它仍然是一个不同的列表

管理器
对象检测到这样的更改,并且在检查
dic2
值的过程中,会无缝更新引用,以便您可以读取正确的值

这里的要点如下:


如果对键或值或两者都没有更改,则线程安全集合(
dict
)不会将任何更改传播到其他进程(或线程)。列表是一种引用类型,因此即使列表值更改,值(即引用)也不会更改。

感谢您的澄清,可惜我之前没有理解。在这种情况下,我的dic2方法是最好的方法吗?我还没有找到更好/更快的方法在这个托管dict中存储三个值并增加它们。等等:3.7文档说在3.6版中更改了
:共享对象可以嵌套。例如,共享容器对象(如共享列表)可以包含其他共享对象,这些对象都将由SyncManager管理和同步。
这是否意味着我的代码在版本3.6+中是正确的?当然,我刚才已经检查过了,我正在使用Python 3.5.6。我相信,只有将字典中的列表创建为
Manager()。list
。可能是,我没有尝试过。如果我试图在3.6+版上使用
+=
,或者在托管目录中使用托管列表,我会尽量记住更新此注释!