【问题标题】:How do I copy a class and its list members in Python 2.7 and not copy the references?如何在 Python 2.7 中复制类及其列表成员而不复制引用?
【发布时间】:2011-11-16 05:07:23
【问题描述】:

我读过这篇关于 Python 类 (link) 的文章,这似乎是我遇到的问题。

这是我的课程和其他代码的摘录:

class s_board:

    def __init__(self):
        self.__board = [[n for n in range(1, 10)] for m in range(81)]
        self.__solved = [False for m in range(81)]

    def copy(self):
        b = s_board()
        b.__board = self.__board[:]
        b.__solved = self.__solved[:]
        return b

if __name__ == '__main__':
    A = s_board()
    B = A.copy()
    B.do_some_operation_on_lists()

当我调用 B 对列表执行某些操作的方法时,A 的列表似乎也受到了影响。

所以我的问题:

  • 我没有正确复制课程或列表吗?
  • 这里还有其他问题吗?
  • 如何修复它以便获得新的课程副本?

【问题讨论】:

    标签: python class copy python-2.7


    【解决方案1】:

    self.__board[:] 创建一个新列表,其中包含对self.__board 中所有相同对象的引用。由于self.__board 包含列表,并且列表是可变的,因此您最终会得到两个具有部分别名数据的s_board 实例,并且更改一个会影响另一个。

    正如 Raymond Hettinger 建议的那样,您可以使用 copy.deepcopy 来(主要)保证您获取对象的真实副本并且不共享任何数据。我说的主要是,因为我相信deepcopy 无法处理一些奇怪的对象,但对于列表和简单类等普通对象,它会正常工作。

    不过,我还有一个额外的建议。你调用b = s_board(),它会全力以赴为新的空白板构建列表,然后通过分配给b.__boardb.__solved 将它们丢弃。似乎最好执行以下操作:

    class s_board:
    
        def __init__(self, board=None, solved=None):
            if board is None:
                self.__board = [[n for n in range(1, 10)] for m in range(81)]
            else:
                self.__board = copy.deepcopy(board)
            if solved is None:
                self.__solved = [False for m in range(81)]
            else:
                self.__solved = copy.deepcopy(solved)
    
        def copy(self):
            b = s_board(self.__board, self.__solved)
            return b
    

    现在,如果您调用A = s_board(),您将获得一个新的空白板,如果您调用A.copy(),您将获得A 的不同副本,而无需分配然后丢弃一个新的空白板。

    【讨论】:

      【解决方案2】:

      尝试使用deepcopy() 而不是copy()

      copy() 可以插入引用,deepcopy() 应该复制所有成员而不使用引用。

      【讨论】:

      • Mike 没有使用copy 模块中的copy,他在自己的类中使用了自己创建的方法。问题是列表列表的切片副本。但是,是的,deepcopy 是解决方案。
      【解决方案3】:

      内部列表正在共享。这是一篇解释正在发生的事情的文章:http://www.python-course.eu/deep_copy.php

      要修复代码,您可以使用 copy.deepcopy 确保没有共享数据:

      def copy(self):
          b = s_board()
          b.__board = copy.deepcopy(self.__board)
          b.__solved = copy.deepcopy(self.__solved)
          return b
      

      【讨论】:

        猜你喜欢
        • 2011-01-28
        • 2023-03-03
        • 2017-03-15
        • 2012-09-03
        • 1970-01-01
        • 2015-10-25
        • 1970-01-01
        • 2011-11-06
        • 2019-09-30
        相关资源
        最近更新 更多