遍历dictionary.items()时字典异常追加旧值问题求助
问题分析与解决:七段数码管模拟类的像素残留问题
问题根源
你遇到的残留像素问题,核心原因是可变对象的引用传递,和字典遍历无关:
- 在
get_digit_pixels方法中,执行digit_pixels[row] = columns时,并没有创建新的列表,而是直接把Segment对象中pixels字典里的列表引用赋值给了digit_pixels。 - 后续执行
digit_pixels[row] += columns时,因为digit_pixels[row]指向的是原Segment的列表,这行代码会直接修改原Segment对象的pixels列表内容,导致后续调用时,原Segment的数据已经被污染。
举个具体例子:第一次调用digit=1时,digit_pixels[4]指向segment_2的[4,5]列表;调用digit=3时,执行digit_pixels[4] += [1,2,3,4],直接把segment_2的pixels[4]改成了[4,5,1,2,3,4],去重后就是[1,2,3,4,5],所以第三次调用digit=1时,取到的已经是被修改后的原数据。
修复方案
只需要在赋值列表时创建副本,避免修改原Segment的列表数据。修改get_digit_pixels方法中的赋值逻辑:
def get_digit_pixels(self, digit): segments = [self.get_segment_by_id(s_id) for s_id in self.digits.get(digit)] digit_pixels = {} for segment in segments: for row, columns in segment.pixels.items(): if digit_pixels.get(row) is not None: digit_pixels[row].extend(columns) else: # 创建列表副本,而非直接引用原列表 digit_pixels[row] = columns.copy() # 也可以用 list(columns) for row, columns in digit_pixels.items(): digit_pixels[row] = list(set(columns)) return digit_pixels
更严谨的写法,全程操作副本避免意外修改:
def get_digit_pixels(self, digit): segments = [self.get_segment_by_id(s_id) for s_id in self.digits.get(digit)] digit_pixels = {} for segment in segments: for row, columns in segment.pixels.items(): # 获取当前行的列表,不存在则创建空列表 current_cols = digit_pixels.get(row, []) # 扩展副本,不影响原Segment的数据 current_cols.extend(columns) digit_pixels[row] = current_cols for row, columns in digit_pixels.items(): digit_pixels[row] = list(set(columns)) return digit_pixels
验证结果
修改后运行示例代码,输出会符合预期:
Digit: 1. Expected output on row 4: [4, 5]. Output on row 4: [4, 5]. Digit: 3. Expected output on row 4: [1, 2, 3, 4, 5]. Output on row 4: [1, 2, 3, 4, 5]. Digit: 1. Expected output on row 4: [4, 5]. Output on row 4: [4, 5].
内容的提问来源于stack exchange,提问作者Julian Fock
相关产品推荐
相关产品推荐

