Python:更新2D字典数组

时间:2018-02-23 23:00:46

标签: python q-learning

我正在开展一个q-learning项目,涉及一个解决迷宫的圈子,这是我如何更新Q值的问题,但我不确定在哪里:我已经合法花了3关于这个话题的日子,我在我的智慧结束。

仔细观察后,Q的每一行中的每一组字典似乎都是相同的(例如:第3行的[Direction.up]值总是 22,即使它不应该& #39;是这样的)

欢迎使用任何指针,这是有问题的代码,希望你能够自己测试一下:

rows=cols=10
for i in range(rows):
    Q.append([{}]*(cols))
    for x in range (cols):
        for y in range (rows):
            Q[x][y][Direction.up]=0
            Q[x][y][Direction.down]=0
            Q[x][y][Direction.left]=0
            Q[x][y][Direction.right]=0
x=5
y=2
Q[x][y][Direction.right]=22
for x in range (cols):
    for y in range (rows):
        print(x," ",y)
        print(Q[x][y])
        print("\n")
    print("\n")

2 个答案:

答案 0 :(得分:3)

一个主要问题是数据结构。我想你想要为每个x,y和方向存储一个值。 但是如果用乘法初始化词典列表

Q = [{}] * 10

你的最终列表是相同字典的十倍,而不是十个不同的字典:

>>> Q = [{}] * 10
>>> Q
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
>>> Q[0]["k"] = "v"
>>> Q
[{'k': 'v'}, {'k': 'v'}, {'k': 'v'}, {'k': 'v'}, {'k': 'v'}, {'k': 'v'}, {'k': 'v'}, {'k': 'v'
}, {'k': 'v'}, {'k': 'v'}]

所以要么在循环中初始化字典

>>> Q = [{} for _ in range(10)]
>>> Q
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
>>> Q[0]["k"] = "v"
>>> Q
[{'k': 'v'}, {}, {}, {}, {}, {}, {}, {}, {}, {}]

或仅使用一个带有元组 (x, y, direction)的字典作为关键字:

Q = {}
for x in range(rows):
    for y in range(cols):
        for dir in Direction:
            Q[(x, y, dir)] = 0

答案 1 :(得分:1)

所以实际问题是你要创建一个cols重复字典{}的列表。

a = [{}]*3
b = [{} for _ in range(3)]
print(id(a[0]), id(a[1]), id(a[2])) # returns 3 times the same identity
print(id(b[0]), id(b[1]), id(b[2])) # returns 3 different identities

问题是乘法运算符*被定义为处理对象。因此,首先评估表达式,然后将对象相乘。在理解中,表达式在每次迭代时都会被评估。

*运算符不知道您的对象内部有表达式和/或想要复制它的任何部分。因此,它生成对同一对象的引用,而不是创建新对象。 乘法运算符的这种行为是语言设计的基本部分,因此它必须是Python的用户,他们必须适应使用它。

顺便提一下,rowscols定义也是如此。

rows = cols = 10
print(id(rows), id(cols)) # identities match

但是,由于整数是不可变的,如果您重新定义cols

,则最终不会更改rows
rows = [3]
print(rows, cols) #[3] 10

如果您使用可变对象,您最终会遇到与您当前的词典问题列表中看到的行为类似的行为:

rows = cols = {}
rows.update({1: 'a'})
print(rows, cols) #{1: 'a'} {1: 'a'}

现在,在我们的任务中,我们在哪里让你的词典按照你想要的方式更新(我冒昧地调整代码的某些部分,我认为它是多余的):

rows=cols=10
for i in range(rows):
    Q.append([{} for _ in range(cols)])
    for x in range(cols):
        Q[x][i][Direction.up]=0
        Q[x][i][Direction.down]=0
        Q[x][i][Direction.left]=0
        Q[x][i][Direction.right]=0
x=5
y=2
Q[x][y][Direction.right]=22
for x in range(cols):
    for y in range(rows):
        print(x, '  ', y, '\n', Q[x][y], '\n', sep='')
    print("\n")