Issue
I have two functions of very similar construction. The first creates a 3D list of dict
s and adds data (the data consisting of the values of the three iterators used to construct the list). The second simply displays the dict
data. The issue is that data displayed by the second function is wrong. Instead of showing values of the iterators increasing as expected:
(0, 9, 19)
(0, 9, 20)
(0, 10, 0)
(0, 10, 1)
(0, 10, 2)
I end up with the maximum value of the iterators being displayed:
(0, 12, 20)
(0, 12, 20)
(0, 12, 20)
(0, 12, 20)
(0, 12, 20)
Code as follows:
xCount = 13
yCount = 21
numPages = 1
skip = [[4, 7], [4, 13], [8, 7], [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, 12, 20 only
# Create text frames.
framesData = createFrames()
# Add data to dictionaries.
displayData(framesData)
Using python 2.7.16.
Solution
The problem comes from the list comprehension. You use frameData
which is mutable, and so everytime you update it, you update it everywhere.
Below is a simplified process that shows the same behaviour:
>>> 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}]
You can use .copy()
to create a copy, or just create the object everytime in the comprehension
>>> a = {"a" : 1}
>>> l2 = [a.copy() for _ in range(3)]
>>> l2[0]["a"] = 2
>>> l2
[{'a': 2}, {'a': 1}, {'a': 1}]
>>> # or
>>> l3 = [{"a" : 1} for _ in range(3)]
>>> l3[0]["a"] = 2
>>> l3
[{'a': 2}, {'a': 1}, {'a': 1}]
Answered By - FlorianGD
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.