如何在Python中使for循环金字塔更简洁?[duplicate]

mzmfm0qo  于 2023-03-04  发布在  Python
关注(0)|答案(4)|浏览(138)
    • 此问题在此处已有答案**:

Avoiding nested for loops(3个答案)
七年前就关门了。
在固体力学中,我经常使用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个字符的限制,并且没有留下太多的空间,特别是如果这又是在类的函数中。

w8rqjzmb

w8rqjzmb1#

通过使用嵌套的for循环,你基本上是在尝试创建输入可迭代的(笛卡尔)乘积,这就是itertools模块中的product函数的作用。

>>> 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),
...

在您的代码中,您可以执行以下操作:

for i,j,k,l in product(range(3),repeat=4):
    #do stuff

根据python文档,“* 此函数大致等同于以下代码,只是实际实现不会在内存中构建中间结果:*”

def product(*args, repeat=1):
    # 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 = [tuple(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)
bpzcxfmw

bpzcxfmw2#

使用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
gwbalxhn

gwbalxhn3#

它不会更简洁,因为它将花费您一个生成器函数,但至少您不会被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

(in python 2.x,则应在生成器函数中使用xrange而不是range
编辑:
当金字塔的深度已知时,上述方法应该是可行的,但是你也可以用这种方法来创建一个通用的生成器,而不需要任何外部模块:

def tup(n, m):
    """ Generate all different tuples of size n consisting of integers < m """
    l = [ 0 for i in range(n)]
    def step(i):
        if i == n : raise StopIteration()
        l[i] += 1
        if l[i] == m:
            l[i] = 0
            step(i+ 1)
    while True:
        yield tuple(l)
        step(0)

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

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

cs7cruho

cs7cruho4#

这相当于:

for c in range(3**4):
    i = c // 3**3 % 3
    j = c // 3**2 % 3
    k = c // 3**1 % 3
    l = c // 3**0 % 3
    print(i,j,k,l)

如果您一直都在这样做,请考虑使用通用生成器:

def nestedLoop(n, l):
    return ((tuple((c//l**x%l for x in range(n-1,-1,-1)))) for c in range(l**n))

for (a,b,c,d) in nestedLoop(4,3):
    print(a,b,c,d)

相关问题