字典操作中的奇怪行为以及 Python 中的多处理
Posted
技术标签:
【中文标题】字典操作中的奇怪行为以及 Python 中的多处理【英文标题】:Strange behavior in dictionary operation along with multiprocessing in Python 【发布时间】:2021-06-22 21:51:58 【问题描述】:我正在学习在 Python 中使用多处理。经过一番研究,我想出了以下代码,它创建了两个对象,池将并行运行该作业。原始代码还有很多其他代码,所以我将其简化为以下原型
import multiprocessing as mp
class GrandParent:
_data = dict()
def __init__(self):
pass
def run(self, num1, num2):
assert (num1 in self._data) and (num2 in self._data)
return self._data[num1] * 232 + self._data[num2] * 101
class Parent(GrandParent):
def __init__(self):
GrandParent.__init__(self)
class Child(Parent):
def __init__(self):
Parent.__init__(self)
self._data[0] = 20
self._data[1] = 100
self._data[2] = 300
def worker(args):
obj, method, num1, num2 = args
return getattr(obj, method)(num1, num2)
if __name__ == '__main__':
a = Child()
print(a._data)
pool = mp.Pool(2)
objList = [Child(), Child()]
ML = ((obj, "run", id, 2) for id, obj in enumerate(objList))
list_results = pool.map(worker, ML)
pool.close()
pool.join()
print(list_results)
代码在池中终止并从assert (num1 in self._data) and (num2 in self._data)
生成错误,通过跟踪代码,我发现_data
是空的,尽管它应该在调用之前分配一些东西(参见@987654326 中的__init__
@)。另外,从python document,我认为直接使用方括号将键值插入字典应该是可以的,上述代码的输出在调用池之前正确打印所有_data
。无论如何它都会清除_data
中的所有键值,所以我尝试更改为使用update
将键值插入字典
class Child(Parent):
def __init__(self):
Parent.__init__(self)
self._data.update(0: 20)
self._data.update(1: 100)
self._data.update(2: 300)
这次代码运行没有错误。这是奇怪的行为。有人可以帮助解释为什么会这样。谢谢
【问题讨论】:
你的 python 和操作系统是什么版本?我的是 3.8.3 和 ubuntu。没有错误。 【参考方案1】:class GrandParent:
def __init__(self):
self._data = dict()
...
解决问题。
您的_data = dict()
创建了一个名为_data
的静态类成员,您每次创建对象时都会重复初始化该成员。但是没有使用__init__
在服务器上创建对象,所以_data从未初始化。
【讨论】:
啊……我想我现在明白了。我对 Python 很陌生,我发现变量是在需要时在 python 中定义的,这与我在其他语言中所知道的完全不同。我是否仍将声明变量保留在类的顶部? 在python 3.8中,你会在类的顶部写:_data: Dict[int,int]
,其中Dict
是从包typing
导入的。在 3.9 中,您将编写 _data: dict[int,int]
。请注意,这不会为变量赋值;这只是一个未强制执行的提示。以上是关于字典操作中的奇怪行为以及 Python 中的多处理的主要内容,如果未能解决你的问题,请参考以下文章