2012-03-20 200 views
4

我在Python/PyMongo中有奇怪的行爲。PyMongo不會迭代集合

dbh = self.__connection__['test'] 
first = dbh['test_1'] 
second = dbh['test_2'] 

first_collection_records=first.find() 
second_collection_records=second.find() 


index_f=first_collection_records.count() //20 
index_s=second_collection_records.count() //120 

i=0 
for f in first_collection_records: 
    for s in second_collection_records: 
     i=i+1 
     print i 

它只打印120次(1..120)而不打印20x120次。有人能告訴我爲什麼它不通過外部收集迭代?我打印的結果,它總是隻需要外部的第一個和迭代內部收集。 (我張貼計數,我在代碼20和120弄,我試着用x範圍和指標,但沒有取)如果你想雖然以second_collection_records迭代爲每first_collection_records

回答

8

,你可以使用:

i=0 
for f in first_collection_records: 
    second_collection_records.rewind() #Reset second_collection_records's iterator 
    for s in second_collection_records: 
     i=i+1 
     print i 

.rewind()將光標重置爲新的狀態,使您可以再次檢索second_collection_records中的數據。


說明:

second.find() 

返回遊標對象,其中包含一個迭代。

當一個Cursor的迭代器到達其末尾時,它不再返回任何東西。

這樣的:

for f in first_collection_records: #20 

實際上並重復20次,但由於內:

for s in second_collection_records: 

已經迭代的所有對象返回,它被稱爲第二次,second_collection_records不再返回任何東西,因此內部代碼(i = i + 1,print ...)不會被執行。

,您可以嘗試這樣的:

i = 0 
for f in first_collection_records: 
    print "in f" 
    for s in second_collection_records: 
     print "inside s" 

你會得到一個結果:

inside f 
inside s 
inside s 
... 
inside s 
inside f <- since s has nothing left to be iterated, 
      (second_collection_records actually raised StopIteration such in generator), 
      code inside for s in second_collection_records: is no longer executed 
inside f 
inside f 

深入的解釋:

這條線:

for s in second_collection_records: 

這裏的循環實際上是通過Cursor對象的next()方法工作的,如下所示:調用second_collection_records.next(),直到second_collection_records引發StopIteration異常(在Python生成器和for循環中,StopIteration被捕獲且for循環內部的代碼不會被執行)。因此,在first_collection_records的第二個直到最後一個循環中,second_collection_records.next()實際上爲內部循環引發了StopIteration,而不是執行代碼。

我們可以很容易地通過這樣觀察此行爲:

for f in first_collection_records: 
    print "inside f" 
    second_collection_records.next() 
    for s in second_collection_records: 
     print "inside s" 

而結果:

inside f 
inside s 
... 
inside s 
inside f 
Traceback (most recent call last): 
    ... , in next 
    raise StopIteration 
StopIteration