为什么这个Punnett广场失败了?

时间:2012-02-04 16:14:30

标签: python

这是我生成小点广场的程序的一部分。它应该将形式[['A','a'],['b','b'],['C',C'] ......]的“基因组”分成可能的配子:

def gene_erator2(gen):
    gam = [[], []]
    q = 0
    for x in gen:
        q = q + 1
        if q > 1:
            gamgam = gam[:]
            for z in gam: 
                gamgam.append(z)
            gam = gamgam[:]
        for y in range(len(gam)):
            if y < len(gam)/2:
                gam[y].append(x[0])
            else:
                gam[y].append(x[1])
    return gam

执行时

gene_erator2([['A','a'], ['B','b'], ['X','Y']])

我得到了

[['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['A', 'B', 'b', 'X', 'X', 'Y', 'Y'], ['a', 'B', 'b', 'X', 'X', 'Y', 'Y']]

而不是预期的

[['A', 'B', 'X'], ['a', 'B', 'X'], ['A', 'b', 'X'], ['a', 'b', 'X], ['A', 'B', 'Y'], ['a', 'B', 'Y'], ['A', 'b', 'Y'], ['a', 'b', 'Y']]

....什么?我的意思是,只是什么?

编辑: 感谢Shang,我现在知道了我想要的功能,但是我仍然想知道我的代码出了什么问题....

3 个答案:

答案 0 :(得分:4)

有一个功能可以在标准库中执行您想要的操作。

import itertools

def gene_erator2(gen):
    return itertools.product(*gen)

这将返回一个迭代器,它允许您遍历所有组合。

>>> i = gene_erator2([['A','a'],['B','b'],['X','Y']])
>>> list(i)
[('A', 'B', 'X'), ('A', 'B', 'Y'), ('A', 'b', 'X'), ('A', 'b', 'Y'), ('a', 'B', 'X'), ('a', 'B', 'Y'), ('a', 'b', 'X'), ('a', 'b', 'Y')]

答案 1 :(得分:1)

除了shang提供的最佳解决方案之外,您的代码中存在很多错误。其中一些是:

I

     gamgam = gam[:]
    for z in gam: 
        gamgam.append(z)
    gam = gamgam[:]

我相信这是gam列表的加倍,但是在行gamgam.append(z)中,您要添加对同一子列表的另一个引用,因此结果将包含对初始子列表对的大量引用。 / p>

II

更新:这标记不是错误,因为gam尺寸在周期中没有增加

 if y < len(gam)/2:
当你将元素附加到gam时,

len(gam)在这种情况下会增加,所以它不会像你想象的那样工作。

所以尽管整个解决方案的丑陋与纠正这两个代码,这个代码将正常工作:

def gene_erator2(gen):
    gam = [[], []]
    q = 0
    for x in gen:
        q = q + 1
        if q > 1:
            gamgam = gam[:]
            for z in gam:
                gamgam.append(z[:])
            gam = gamgam[:] 
        lenGam = len(gam)
        for y in range(lenGam):
            if y < lenGam/2:
                gam[y].append(x[0])
            else:
                gam[y].append(x[1])
    return gam

<强> UPD: 根据要求,这是某种pythonic重新编码itertools.product

def product(collections):
    if collections:
        for subproduct in product(collections[1:]):
            for element in collections[0]:
                yield list(element) + subproduct

    else: yield []

def gene_erator2(gen): return list(product(gen))

也建议在这种情况下使用元组而不是列表。

答案 2 :(得分:1)

另一种解决问题的方法,不使用itertools.product

def gene_erator2(args):
    result = [[]]
    for pool in args:
        result = [x+[y] for x in result for y in pool]
    return result

另请查看itertools.product的{​​{3}}。