Python: 更新二维字典数组

Python: updating a 2D array of dictionaries

我正在做一个 q-learning 项目,它涉及一个圆圈来解决迷宫问题,这是我如何更新 Q 值的问题,但我不确定在哪里:我合法地花了 3 天时间现在进入主题,我已经无计可施了。

经过仔细检查,似乎 Q 的每一行中的每组词典都是相同的(例如:第 3 行 [Direction.up] 的值是 always 22,即使事实并非如此)

欢迎任何指点,这是有问题的代码,希望足够让你自己测试:

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")

一个主要问题是数据结构。我猜你想为每个 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

所以实际的问题是您正在创建 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

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

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

顺便说一句,rowscols 定义也是如此。

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

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

,您将不会以更改 cols 告终
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")