我正在尝试在python中创建一个3D索引列表。我可以做的一种方法是迭代嵌套循环中的所有id,并按如下方式执行:
l = list()
for z in range(0, 2):
for y in range(1, 5);
for x in range(1, 10):
l.append((x, y, z))
然而,我记得有一种单行方式可以做到这一点但是对于我的生活我无法理解。我试过像:
l.append((x, y, z) for x in range(0, 10), for y in range(0, 10), for z in range(0, 2))
但是,这导致了语法错误。
答案 0 :(得分:6)
你打算写:
l = [(x, y, z) for x in range(0, 10) for y in range(0, 10) for z in range(0, 2)]
range()
调用后,您无需使用逗号,您可以直接将结果(列表)分配给变量l
。
答案 1 :(得分:6)
你得到了SyntaxError,因为
(x, y, z) for x in range(0, 10), for y in range(0, 10), for z in range(0, 2)
用逗号分隔for
个表达式。但根据grammar for list comprehension,
comprehension ::= expression comp_for
comp_for ::= "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" expression_nocond [comp_iter]
逗号不应该在那里。
现在,即使删除了逗号,您的程序也会出现逻辑错误
>>> l = []
>>> l.append((x, y, z) for x in range(10) for y in range(10) for z in range(2))
>>> l
[<generator object <genexpr> at 0x7f5b78302b40>]
这里,表达式(x, y, z) for x in range(0, 10) for y in range(0, 10) for z in range(0, 2)
被视为生成器表达式。因此,您需要使用list
函数创建一个列表,如此
>>> list((x, y, z) for x in range(1) for y in range(2) for z in range(2))
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)]
相反,您可以使用列表推导来创建新列表,例如
>>> [(x, y, z) for x in range(1) for y in range(2) for z in range(2)]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)]
但是,在这种情况下,您也可以使用itertools.product
>>> from itertools import product
>>> list(product(range(1), range(2), range(2)))
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)]
product
函数返回一个生成器,为了得到实际的整个列表,我们使用list
函数。
PS:如果它是零,您就不会使用range
函数中的起始值,因为这是默认值。
注意:您实际上要做的是生成三次迭代的笛卡尔积。结果将有大量的元素。因此,除非您一次需要所有元素,否则您只需迭代product
的结果即可。这将大大提高程序的性能,因为不需要立即计算整个结果。
>>> for items in product(range(1), range(2), range(2)):
... print(items)
...
...
(0, 0, 0)
(0, 0, 1)
(0, 1, 0)
(0, 1, 1)
现在,仅在各自的迭代期间生成值。