2011-04-22 36 views
4

你知道你可以做到這一點嗎?python:單行笛卡爾積for循環

>>> [(x,y) for x in xrange(2) for y in xrange(5)] 
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4)] 

它很整齊。有沒有for循環版本,或者只能爲列表解析做這個?

編輯:我想我的問題被誤解了。我想知道是否有這個特殊的語法:

for x in xrange(2) <AND> y in xrange(5): 
    print "do stuff here" 
    print "which doesn't fit into a list comprehension" 
    print "like printing x and y cause print is a statement", x, y 

我能做到這一點,但它似乎有點重複:

for x,y in ((x,y) for x in xrange(2) for y in xrange(5)): 
    print x, y 
+3

不,你不能。這只是列表理解。 – rubik 2011-04-22 20:38:33

+1

+1 rubik是正確的,這是不支持的語法。 – samplebias 2011-04-22 20:40:16

+0

@samplebias:啊如果只有一個人可以接受評論作爲回答 – Claudiu 2011-04-22 20:41:00

回答

7

那麼沒有你想要的語法,但有itertools.product

>>> import itertools 
>>> for x, y in itertools.product([1,2,3,4], [5,6,7,8]): print x, y 
... 
1 5 
1 6 
1 7 
1 8 
[ ... and so on ... ] 
5

這是一個等價的,更緊湊版本:

def values(): 
    for x in xrange(2): 
     for y in xrange(5): 
      yield (x, y) 
list(values()) 

更新:比較兩個字節碼,這樣做:

import dis 
print dis.dis(values) # above function 

gen = ((x,y) for x in xrange(2) for y in xrange(5)) 
print dis.dis(gen.gi_code) 
+0

是一個確切的等值? (python實際上是爲每個列表理解產生一個生成器嗎?)。否則,當然輸出將是相同的 – Claudiu 2011-04-22 20:40:03

+0

是的,字節碼是非常接近,雖然我認爲發電機效率更高一點。 – samplebias 2011-04-22 20:44:51

+0

那麼,它當然不會爲每個列表理解定義完全一次性發生器。它也不會將其展開到Python級循環中。但是這樣的實現細節並不重要,而且這個例子定義了一個生成器也沒有。這是重要的循環嵌套。 (編輯:爲了挑選,OP使用列表理解,這與特殊的字節碼有不同的實現!) – delnan 2011-04-22 20:45:22