【问题标题】:Copying nested custom objects: alternatives to deepcopy复制嵌套的自定义对象:deepcopy 的替代方案
【发布时间】:2016-08-18 23:25:19
【问题描述】:

我正在寻找一个包含类对象列表的类对象的深层副本,每个类对象都有自己的一组东西。这些对象不包含比整数和列表更令人兴奋的东西(没有字典,没有等待产生的生成器等)。我在一个循环中对 500-800 个对象执行深度复制,这确实减慢了程序的速度。我意识到这已经是低效的;目前无法更改。

外观示例:

import random
import copy

class Base:
    def __init__(self, minimum, maximum, length):
        self.minimum = minimum
        self.maximum = maximum
        self.numbers = [random.randint(minimum, maximum) for _ in range(length)]
        # etc

class Next:
    def __init__(self, minimum, maximum, length, quantity):
        self.minimum = minimum
        self.maximum = maximum
        self.bases = [Base(minimum, maximum, length) for _ in range(quantity)]
        # etc

由于我对对象执行的操作,我无法进行浅拷贝。我需要新变量拥有的内容:

> first = Next(0, 10, 5, 10)
> second = first
> first.bases[0].numbers[1] = 4
> print(first.bases[0].numbers)
> [2, 4, 3, 3, 8]
> print(second.bases[0].numbers)
> [2, 4, 3, 3, 8]
>
> first = Next(0, 10, 5, 10)
> second = copy.deepcopy(first)
> first.bases[0].numbers[1] = 4
> print(first.bases[0].numbers)
> [8, 4, 7, 9, 9]
> print(second.bases[0].numbers)
> [8, 11, 7, 9, 9]

我尝试了几种不同的方法,例如使用 json 序列化和重新加载数据,但在我的测试中,它的速度还不够快,因为我每次都要重新分配所有变量。由于嵌套对象,我尝试使用聪明的self.__dict__ = dct 并没有奏效。

关于如何在不使用 copy.deepcopy 的情况下有效地深度复制多重嵌套的 Python 对象的任何想法?

【问题讨论】:

  • 您可能想考虑将数据项存储为基元(例如整数和字符串)而不是 Python 对象的方法。复制这些会更有效率。也许数组模块甚至 cython 语言会很有用。

标签: python python-3.x


【解决方案1】:

根据 cherish 的回答 herepickle.loads(pickle.dumps(first)) 每次通话的速度大约是两倍。由于测试时出现不相关的错误,我最初将其注销,但在重新测试时,它在我的需求范围内表现良好。

【讨论】:

    【解决方案2】:

    copy.deepcopy 查找的第一件事是对象是否定义了it's own __deepcopy__ method 所以不要让它每次都弄清楚如何复制对象,只需定义您自己的进程即可。

    这将要求您有一种方法来定义 Base 对象,而不需要任何随机元素供副本使用,但如果您能找到更有效的复制对象的过程,您应该将其定义为 @ 987654325@加速复制过程的方法。

    【讨论】:

    • 我不确定自定义 __deepcopy__ 在这里能提供多大帮助。默认实现已经复制了所有属性,它避免了在新对象上调用__init__,所以你不会遇到随机东西的任何问题。我认为提高性能的唯一明确方法是要么显着改变数据结构(例如使用numpy 数组或其他东西,而不是对象列表),要么改变整个算法以避免所有复制的需要。跨度>
    • 我尝试了这个,但无法获得我希望的速度提升(毫无疑问,我在实现它时出现了错误)。我发现使用 pickle.loads(pickle.dumps(first)) 的速度大约是 deepcopy 的两倍。感谢您的帮助!
    猜你喜欢
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2016-11-22
    • 2017-09-03
    相关资源
    最近更新 更多