Python:如何优雅地得到这个?

Python: how to get this elegantly?

本问题已经有最佳答案,请猛点这里访问。

我对python不熟悉,我编写了一个函数:

1
2
3
4
5
6
7
8
9
10
def f(x, y, z):
    ret = []
    for i in range(x):
        for j in range(y):
            for k in range(z):
                ret.append((i, j, k))
    return ret


print f(2, 3, 4)

输出:

1
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3)]

但我对此并不满意,因为我认为必须有一个更短的实现。

有人能给我一些提示吗?


你可以使用itertools.product,因为这基本上就是你想要的,笛卡尔积

1
2
3
>>> from itertools import product
>>> list(product(range(2), range(3), range(4)))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3)]

所以替换你现有的功能

1
2
def f(x, y, z):
    return list(product(range(x), range(y), range(z)))

要删除必须键入range的次数,可以接受单个列表参数,然后使用生成器表达式,例如

1
2
def f(l):
    return list(product(*(range(i) for i in l)))

所以你可以称之为

1
2
>>> f([2,3,4])
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3)]


您可以使用list comprehension

1
2
 >>> [(i, j, k) for i in range(2) for j in range(3) for k in range(4)]
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 2, 3), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 0, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3)]

您可以编写如下函数:

1
2
def f(x, y, z):
    return [(i, j, k) for i in range(x) for j in range(y) for k in range(z)]