📜  Python|列表列表中的自定义乘法(1)

📅  最后修改于: 2023-12-03 14:46:26.695000             🧑  作者: Mango

Python | 列表列表中的自定义乘法

在 Python 中,我们通常使用 * 操作符来对列表或其他对象进行复制或重复操作,例如:

>>> [1, 2, 3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

但是,对于列表列表(嵌套列表)来说,* 操作符的行为可能不是我们所期望的:

>>> [[0] * 3] * 3
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> [[0 for _ in range(3)] for _ in range(3)]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

这是因为嵌套列表中的每个子列表是用同一个内存地址复制的,由此导致其中一个子列表的值发生改变会影响到其他子列表。为了避免这种情况,我们通常需要自定义乘法操作符来创建一个新的嵌套列表。

我们可以使用以下方法来定义自定义乘法操作符:

class RepeatableList(list):
    def __mul__(self, n):
        return RepeatableList([self.copy() for _ in range(n)])

这个类继承自 list 并重写了其 __mul__ 方法。当我们对一个 RepeatableList 对象使用 * 操作符时,会返回一个新的 RepeatableList 对象,其中包含输入 RepeatableListn 个副本。这些副本是通过 list.copy() 创建的,因此它们具有独立的内存地址。

接下来,我们可以使用 RepeatableList 来创建一个嵌套列表,并使用自定义乘法操作符来复制每个子列表。

>>> matrix = RepeatableList([[0] * 3] * 3)
>>> matrix
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

>>> matrix[0][0] = 1
>>> matrix
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]

现在,我们可以在不影响其他子列表的情况下,修改任意一个子列表的值。

需要注意的是,list.copy() 方法只会复制第一级列表中的元素。如果 RepeatableList 对象包含嵌套的列表,则需要使用递归方法进行深层复制。

class RepeatableList(list):
    def __mul__(self, n):
        return RepeatableList([self.__recursive_copy() for _ in range(n)])
    
    def __recursive_copy(self):
        if isinstance(self, RepeatableList):
            return RepeatableList([el.__recursive_copy() if isinstance(el, RepeatableList) else el for el in self])
        else:
            return self.copy()

现在,我们可以使用 RepeatableList 来创建任意层级的嵌套列表,并使用自定义乘法操作符进行复制操作而不会改变其他子列表的值了。