微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

循环迭代器意外行为

如何解决循环迭代器意外行为

我有两个结构非常相似的函数。第一个创建 dict 的 3D 列表并添加数据(数据由用于构造列表的三个迭代器的值组成)。第二个只是显示 dict 数据。问题是第二个函数显示的数据是错误的。而不是显示迭代器的值按预期增加

(0,9,19)
(0,20)
(0,10,0)
(0,1)
(0,2)

我最终得到了显示的迭代器的最大值:

(0,12,20)

代码如下:

xCount = 13
yCount = 21
numPages = 1
skip = [[4,7],[4,13],[8,13]]

def createFrames():
  frameData = {'textFrameName': ''}
  framesData = [[[frameData for y in range(yCount)] for x in range(xCount)] for p in range(numPages)]

  for p in range(numPages):
    for x in range(xCount):
      for y in range(yCount):

        skipFrame = False

        for entry in skip:
          if entry[0] == x and entry[1] == y:
            skipFrame = True

        if skipFrame == False:
          framesData[p][x][y]['textFrameName'] = str(p) + ',' + str(x) + ',' + str(y)
          print(framesData[p][x][y]['textFrameName']) # shows p,x,y incrementing

  return framesData

def displayData(framesData):
  for p in range(numPages):
    for x in range(xCount):
      for y in range(yCount):

        skipFrame = False

        for entry in skip:
          if entry[0] == x and entry[1] == y:
            skipFrame = True

        if skipFrame == False:
          print(framesData[p][x][y]['textFrameName']) # shows 0,20 only


# Create text frames.
framesData = createFrames()

# Add data to dictionaries.
displayData(framesData)

使用 python 2.7.16。

解决方法

问题来自于列表理解。您使用的是可变的 frameData,因此每次更新它时,都会在任何地方更新它。

以下是显示相同行为的简化过程:

>>> a = {"a" : 1}
>>> l = [a for _ in range(3)]
>>> l
[{'a': 1},{'a': 1},{'a': 1}]
>>> l[0]["a"] = 2
>>> l
[{'a': 2},{'a': 2},{'a': 2}] 

您可以使用.copy()来创建副本,也可以在理解中每次都创建对象

>>> a = {"a" : 1}
>>> l2 = [a.copy() for _ in range(3)]
>>> l2[0]["a"] = 2
>>> l2
[{'a': 2},{'a': 1}]
>>> # or
>>> l3 = [{"a" : 1} for _ in range(3)]
>>> l3[0]["a"] = 2
>>> l3
[{'a': 2},{'a': 1}]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。