如何重新分配行为?

时间:2016-04-13 13:35:10

标签: python list tuples itertools

我在这里产生了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])

然而上面这些行中的印刷语句向我显示它们被正确分配,但是在一个'级别'后面的分配('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])

这种行为是如何产生的?为什么它在内循环中不可见但在外循环中不可见?我觉得它可能与评估的顺序和元组/列表的打包方式有关。

如何实现目标输出?

1 个答案:

答案 0 :(得分:1)

您的问题是path中每个paths内的所有列表成员都是同一个对象。要自己验证 - 请尝试:

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"以下 - 虽然整篇文章真的值得一读。

如何解决此问题将高度依赖于此代码的上下文。