如何使forloop金字塔在Python中更简洁?

2024-05-13 21:49:46 发布

您现在位置:Python中文网/ 问答频道 /正文

在实体力学中,我经常使用Python编写如下代码:

for i in range(3):
    for j in range(3):
        for k in range(3):
            for l in range(3):
                # do stuff

我经常这样做,以至于我开始怀疑是否有更简洁的方法来做到这一点。当前代码的缺点是:如果我遵守PEP8,那么我不能超过每行79个字符的限制,并且没有太多的空间,特别是如果这又是在类的函数中。在


Tags: 方法函数代码in实体for空间range
3条回答

根据您想要做的,您可以使用^{}模块来最小化for循环(或^{})。在这种情况下,^{}将创建您对4个循环所做的操作:

>>> list(product(range(3),repeat=4))
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 1, 0), (0, 0, 1, 1),
 (0, 0, 1, 2), (0, 0, 2, 0), (0, 0, 2, 1), (0, 0, 2, 2), (0, 1, 0, 0),
 (0, 1, 0, 1), (0, 1, 0, 2), (0, 1, 1, 0), (0, 1, 1, 1), (0, 1, 1, 2),
 (0, 1, 2, 0), (0, 1, 2, 1), (0, 1, 2, 2), (0, 2, 0, 0), (0, 2, 0, 1),
 (0, 2, 0, 2), (0, 2, 1, 0), (0, 2, 1, 1), (0, 2, 1, 2), (0, 2, 2, 0),
 (0, 2, 2, 1), (0, 2, 2, 2), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 0, 2),
 (1, 0, 1, 0), (1, 0, 1, 1), (1, 0, 1, 2), (1, 0, 2, 0), (1, 0, 2, 1),
 (1, 0, 2, 2), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 0, 2), (1, 1, 1, 0),
 (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 0), (1, 1, 2, 1), (1, 1, 2, 2),
 (1, 2, 0, 0), (1, 2, 0, 1), (1, 2, 0, 2), (1, 2, 1, 0), (1, 2, 1, 1),
 (1, 2, 1, 2), (1, 2, 2, 0), (1, 2, 2, 1), (1, 2, 2, 2), (2, 0, 0, 0),
 (2, 0, 0, 1), (2, 0, 0, 2), (2, 0, 1, 0), (2, 0, 1, 1), (2, 0, 1, 2),
 (2, 0, 2, 0), (2, 0, 2, 1), (2, 0, 2, 2), (2, 1, 0, 0), (2, 1, 0, 1),
 (2, 1, 0, 2), (2, 1, 1, 0), (2, 1, 1, 1), (2, 1, 1, 2), (2, 1, 2, 0),
 (2, 1, 2, 1), (2, 1, 2, 2), (2, 2, 0, 0), (2, 2, 0, 1), (2, 2, 0, 2),
 (2, 2, 1, 0), (2, 2, 1, 1), (2, 2, 1, 2), (2, 2, 2, 0), (2, 2, 2, 1),
 (2, 2, 2, 2)]

在您的代码中,您可以:

^{pr2}$

This function is equivalent to the following code, except that the actual implementation does not build up intermediate results in memory:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

编辑:正如@PeterE在评论中所说,product()即使范围长度不同,也可以使用:

product(range(3),range(4),['a','b','c'] ,some_other_iterable)

它不会更简洁,因为它会花费您一个生成器函数,但至少您不会被PEP8困扰:

def tup4(n):
    for i in range(n):
        for j in range(n):
            for k in range(n):
                for l in range(n):
                    yield (i, j, k, l)

for (i, j, k, l) in tup4(3):
    # do your stuff

(在python2.x中,您应该在generator函数中使用xrange而不是{})

编辑:

当已知金字塔的深度时,上述方法应该是好的。但您也可以通过这种方式制作通用生成器,而无需任何外部模块:

^{pr2}$

(我使用(l, k, j, i),因为在上面的生成器中,第一个索引首先变化)

使用itertools.product是个好主意。这里有一个更通用的方法,可以支持不同大小的范围。在

from itertools import product

def product_of_ranges(*ns):
    for t in product(*map(range, ns)):
        yield t

for i, j, k in product_of_ranges(4, 2, 3):
    # do stuff

相关问题 更多 >