Remove函数更改不相关for循环(Python)的元素

Remove函数更改不相关for循环(Python)的元素,python,Python,我尝试删除数据库中小于所选字符I的所有字符。数据库是字符列表的列表 def project(database, i): test = database.copy() for idx,lists in enumerate(database.copy()): for char in lists: print(char) if char <= i: test[idx].remove(c

我尝试删除数据库中小于所选字符I的所有字符。数据库是字符列表的列表

def project(database, i):
    test = database.copy()
    for idx,lists in enumerate(database.copy()):
        for char in lists:
            print(char)
            if char <= i:
                test[idx].remove(char)
     return test

a = [['A','B','D'],['A','B','C','D']]
print(project(a, 'C'))


Output:
A D A C
[['B', 'D'], ['B', 'D']]
虽然我没有更改迭代列表,但为什么打印的字符会更改?

调试后:

问题不是因为if语句,而是因为remove更改了索引

让mt证明:

  • 在第一次迭代删除后,列表将为:

    ["B", "D"]
    

您的索引将是1,因为
“B”
将被忽略。

您的问题与您复制列表
数据库有关

根据:

浅复制构造一个新的复合对象,然后(尽可能)向其中插入对原始对象的引用

深度副本构造一个新的复合对象,然后递归地将在原始副本中找到的对象的副本插入其中


如果您深度复制
copy.deepcopy(x)
您的列表,那么您将得到一个单独的对象,它不是另一个对象的引用,而是一个完整的副本。

正如其他答案中已经提到的,您的代码有两个问题:一个是浅复制,另一个是修改正在迭代的列表。然而,您甚至不需要所有这些复杂性。在您的情况下,保留“好”项目比删除“坏”项目更便宜:


顺便说一下,条件
char
test
不是
数据库的副本。是的,但这是一个肤浅的复制品。它包含对原始内部列表的引用。你需要一个深度副本。我担心改变我正在迭代的矩阵可能会解释这种奇怪的行为。我只是检查了没有所有副本的代码,它也一样。请阅读答案,其中至少有一个解释了如何制作深度副本。深度副本如何修复了此问题?可能的副本也请参阅
["B", "D"]
def project(database, i):
    return [[item for item in lst if item >= i] for lst in database]

print(project(a, 'C'))
# [['D'], ['C', 'D']]