重新分配行为是如何出现的?
How does the re-assignment behaviour emerge?
我在这里生成超过 6 个位置的两种可能结果的所有可能排列:
paths = list(it.product([['ax','r',[],0], ['ax','l',[],0]], repeat=6))
它应该生成的是这样的:
(['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax',
'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0])
这是包含所有结果的列表的一个元素。
我现在想根据重复模式更改 'ax' 字符串
'yp', 'p', 'xp'
为此我写了这样的东西:
for path in paths:
axis = 1
for axis_slice in path:
if(axis%3 == 1):
axis_slice[0] = 'yp'
print(axis_slice[0])
elif(axis%3 == 2):
axis_slice[0] = 'p'
print(axis_slice[0])
elif(axis%3 == 0):
axis_slice[0] = 'xp'
print(axis_slice[0])
axis+=1
print("axis: "+str(axis))
print(path)
然而结果是这样的:
(['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0])
然而,上面几行中的打印语句向我显示它们已正确分配,但要 'level' 返回分配('yp'、'p'、'xp') 分歧
yp
p
xp
yp
p
xp
axis: 7
(['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0])
这种行为是如何出现的?为什么在内循环中看不到,而在外循环中呢?我感觉这可能与评估顺序和 tuples/lists 的打包方式有关。
如何才能达到目标输出?
您的问题是 paths
中每个 path
中列表的所有成员都是同一个对象。要自己验证这一点 - 尝试:
import itertools as it
paths = list(it.product([['ax','r',[],0], ['ax','l',[],0]], repeat=6))
for path in paths:
print([id(p) for p in path])
这将打印路径中每个列表的唯一标识符。您会看到您只有两个 ID - 您传递给 it.product
.
的原始两个列表的 ID
因此,例如,如果您选择第一条路径:
(['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0])
它实际上是对同一个列表的 6 个引用的元组。因此,当您遍历它们时,您每次都会更改相同的列表。如果每次更改它时您使用 print(path)
而不是 axis_slice[0]
,您将清楚地看到发生了什么 - path
的所有 6 个成员每次都会更改。这是列表可变性和在具有可变成员的列表上使用 itertools.product
的一个特性。
Python 和 SO 老手 Ned Batchelder here 很好地涵盖了这种效果。特别是 - 查看名为 "Mutable aliasing" 的幻灯片和以下 - 尽管整篇文章确实值得一读。
如何解决这个问题将在很大程度上取决于这段代码的上下文。
我在这里生成超过 6 个位置的两种可能结果的所有可能排列:
paths = list(it.product([['ax','r',[],0], ['ax','l',[],0]], repeat=6))
它应该生成的是这样的:
(['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax',
'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0])
这是包含所有结果的列表的一个元素。
我现在想根据重复模式更改 'ax' 字符串
'yp', 'p', 'xp'
为此我写了这样的东西:
for path in paths:
axis = 1
for axis_slice in path:
if(axis%3 == 1):
axis_slice[0] = 'yp'
print(axis_slice[0])
elif(axis%3 == 2):
axis_slice[0] = 'p'
print(axis_slice[0])
elif(axis%3 == 0):
axis_slice[0] = 'xp'
print(axis_slice[0])
axis+=1
print("axis: "+str(axis))
print(path)
然而结果是这样的:
(['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0])
然而,上面几行中的打印语句向我显示它们已正确分配,但要 'level' 返回分配('yp'、'p'、'xp') 分歧
yp
p
xp
yp
p
xp
axis: 7
(['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0], ['xp', 'r', [], 0])
这种行为是如何出现的?为什么在内循环中看不到,而在外循环中呢?我感觉这可能与评估顺序和 tuples/lists 的打包方式有关。
如何才能达到目标输出?
您的问题是 paths
中每个 path
中列表的所有成员都是同一个对象。要自己验证这一点 - 尝试:
import itertools as it
paths = list(it.product([['ax','r',[],0], ['ax','l',[],0]], repeat=6))
for path in paths:
print([id(p) for p in path])
这将打印路径中每个列表的唯一标识符。您会看到您只有两个 ID - 您传递给 it.product
.
因此,例如,如果您选择第一条路径:
(['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0], ['ax', 'r', [], 0])
它实际上是对同一个列表的 6 个引用的元组。因此,当您遍历它们时,您每次都会更改相同的列表。如果每次更改它时您使用 print(path)
而不是 axis_slice[0]
,您将清楚地看到发生了什么 - path
的所有 6 个成员每次都会更改。这是列表可变性和在具有可变成员的列表上使用 itertools.product
的一个特性。
Python 和 SO 老手 Ned Batchelder here 很好地涵盖了这种效果。特别是 - 查看名为 "Mutable aliasing" 的幻灯片和以下 - 尽管整篇文章确实值得一读。
如何解决这个问题将在很大程度上取决于这段代码的上下文。