美文网首页
关于python对象在容器中型态的一个问题

关于python对象在容器中型态的一个问题

作者: 东方胖 | 来源:发表于2022-07-20 12:58 被阅读0次

本文讨论的话题涉及python的容器,内存管理和深浅拷贝

考虑一个任务

从另一个系统中我们会的得到一批数据,我们对它进行某种 X 操作,然后放到队列中 q2 中,等待存储例程将这些消息入库

这个任务升级,有一定概率我们需要对消息进行 X 的逆操作,具体来说就是,当触发逆操作时,我们需要从之前做过 X 操作的message 取一条,修改message的一个属性,然后将该message执行逆操作,并且把新的message 存入队列 q2 中等待入库

一个存储任务 save_task ,负责将处理记录写入db进行持久存储 ,它负责不断从 q2 中取出message 入库

我们容易做一个样的实现:

  1. 构建一个 buffer 队列,把进行过 X 操作的message 放到buffer中, 如果触发了逆操作,我们就从中哪一个message出来取逆,处理完以后交给 q2.

如图

草图.png

这个任务容易出现一种怪现象: 入库数据 的逆操作数据总出现重复记录
示例代码

psudo code

from queue import Queue
buffer = Queue()
q2 = Queue()

if random.randomint(a, b) < a:
     do_x(message)
     buffer.put(message)
     q2.put(message)
elif not buffer.empty():
     msg = buffer.get()
     do_inverse_x(msg)
     msg.status = 2
     msg.trace_id = "inverse_" + msg.trace_id
     q2.put(msg)

save_task()

原因是buffer 和 q1 的对象默认情况下是共享内存的, 出发逆操作后,buffer的数据取出并被修改,直接影响了q2中尚未被处理的对象内存。
举例子而言。
q1 今有 [a, b, c] 三条数据
随机产生 1,从队尾拿到 c,进行 X 工序后,原封不动放到 buffer ,同时 c 放到q2;
再次随机产生 0 , 我们要在buffer里去一条数据做逆操作,取出 c ,我们将它改成 C 做完逆操作后,交给 q2;
修改数据时,q2的 c也被改成了 C,C再次被添加到 q2时,q2中就有了两份数据一模一样但对象id的数据。

因此就会看到数据库总是会出现两条逆操作的数据,一模一样。

本质是一个副本两处存储可变对象惹的祸

Python的多数容器存储对象时,为了节省内存都是默认存储对象的引用,而非内存,因此一旦一个对象你要修改挪作他用的时候,最后的办法是用 copy.copy() 全新地复刻一个新对象出来,而不是直接在可变对象上直接修改。

总结

当一个对象存储在两个容器时,写操作容易引起一个联动的变化——两处内存同时被修改。这一般不是期望的,因此,一般我们准备要作写操作时,要进行深拷贝,不直接使用赋值 “=”,而是用 copy模块里的copy方法

相关文章

  • 关于python对象在容器中型态的一个问题

    本文讨论的话题涉及python的容器,内存管理和深浅拷贝 考虑一个任务 从另一个系统中我们会的得到一批数据,我们对...

  • Python-for循环的内部机制

    Python中,使用for循环可以迭代容器对象中的元素,这里容器对象包括是列表(list)、元组(tuple)、字...

  • Python进阶——什么是迭代器?

    Python进阶——什么是迭代器? 在 Python 开发中,我们经常听到有关「容器」、「迭代器」、「可迭代对象」...

  • python元类和三个对象概念

    在python中,关于对象权威的说法是metaclasses,classes,instance三类对象python...

  • [笔记] Python核心编程 第七章

    一个字典对象是可变的,它是一个容器类型,能存储任意个数的Python对象,其中也包括其他容器类型。字典类型中的数据...

  • Effective STL 第7条

    容器中的对象如果是指针,指针指向的资源,容器没有办法自动释放. 问题引出 容器在自己析构的时候,会把包含的对象逐个...

  • Python 中的迭代器

    Python 中的迭代器 Python 3中的迭代器 容器与迭代器 在Python 3中,支持迭代器的容器,只要支...

  • Spring 学习笔记(二):Spring 容器以及 bean

    Spring 容器 在 Spring 应用中,应用对象生存于 Spring 容器中,Spring 容器负责创建对象...

  • spring 学习02

    Spring 容器 在Spring 应用中,你的应用对象生存在Spring容器中,Spring 容器负责创建对象,...

  • python迭代器和生成器

    迭代器 在 Python 中一切皆对象,对象的抽象就是类,而对象的集合就是容器。对于容器,你可以很直观地想象成多个...

网友评论

      本文标题:关于python对象在容器中型态的一个问题

      本文链接:https://www.haomeiwen.com/subject/tmbeirtx.html