Python中对比两个数据库表名列表时,无法正确获取第二个列表唯一表名的问题排查
嗨,我来帮你揪出这个代码bug的核心——这是一个典型的可变对象引用赋值引发的意外修改问题,咱们一步步拆解:
1. 关键错误点
看这段代码:
unique_total_tables = d1_tables
列表是Python中的可变对象,这行代码并没有创建新的列表副本,而是让unique_total_tables和d1_tables指向内存中同一个列表。
接下来你执行了扩展操作:
unique_total_tables.extend(x for x in tab_list if x not in unique_total_tables)
这一步实际上直接修改了d1_tables的内容——因为两个变量指向同一个列表!你把root数据库中不在old_root的表全部加到了d1_tables里,导致d1_tables现在包含了old_root的所有表 + root独有的表。
2. 为什么最后一行输出是0?
当你计算unique_d2_tables时:
unique_d2_tables.extend(x for x in d2_tables if x not in d1_tables)
此时d1_tables已经被扩展成包含root所有表的列表(root独有的表已经被加进去了),所以x not in d1_tables对root的所有表都返回False,自然unique_d2_tables是空列表,输出0。
你看输出里的Total number of tables in both old_root & root (excluding duplicates): 484,309(old_root)+175(root独有)=484,这也验证了d1_tables确实被修改成了包含root所有表的列表。
3. 修复方案
只需要把列表的引用赋值改成创建副本,让unique_total_tables和d1_tables成为独立的列表即可:
# 替换原来的 unique_total_tables = d1_tables unique_total_tables = d1_tables.copy() # 或者用 list(d1_tables)
修复后的代码运行后,d1_tables会保持原来的old_root表列表,后续计算unique_d2_tables时就能正确找出root独有的表,输出预期的175。
额外优化建议(可选)
用Python的set(集合)来处理这种去重、差集的场景会更高效,代码也更简洁,不容易出错:
# 把列表转成集合 d1_set = set(d1_tables) d2_set = set(d2_tables) # 计算各种集合操作 unique_total = d1_set.union(d2_set) unique_d1 = d1_set - d2_set unique_d2 = d2_set - d1_set # 输出结果 print("Total number of tables in both old_root & root (excluding duplicates):", len(unique_total)) print("Total number of tables in old_root not present in root:", len(unique_d1)) print("Total number of tables in root not present in old_root:", len(unique_d2))
集合的差集、并集操作时间复杂度远高于列表遍历,当表数量较多时优势更明显。
内容的提问来源于stack exchange,提问作者Allgemeine Models

