字典操作中的奇怪行为以及 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 中的多处理的主要内容,如果未能解决你的问题,请参考以下文章

异常处理中的这种奇怪行为是啥?

python(pytz)中的奇怪时区行为

列表理解中的Python奇怪行为[重复]

Visual Studio中的奇怪Python包导入行为

Python元类的__new__方法中的奇怪行为[重复]

VBA 中 Scripting.Dictionary 类的 .item() 方法的奇怪行为