2014-03-27 58 views
3

爲什麼這個代碼拋出 「的StopIteration」:分配產生直接字典拋出StopIteration異常

stub_generator = (x for x in range(5)) 
stub_dict = {} 
stub_dict[next(stub_generator)] = list(stub_generator) 

和工作的嗎?

stub_generator = (x for x in range(5)) 
stub_dict = {} 
temp_1 = next(stub_generator) 
temp_2 = list(stub_generator) 
stub_dict[temp_1] = temp_2 

回答

3

此行爲是因爲兩件事情:

  1. 賦值語句的右手邊的左側前進行評估。

  2. 生成器對象只能迭代一次。


爲了進一步解釋,當執行這樣的代碼:

stub_dict[next(stub_generator)] = list(stub_generator) 

這一部分:

list(stub_generator) 

將之前評估這一部分:

stub_dict[next(stub_generator)] 

此外,將stub_generator置於list將導致發生器完全迭代並因此耗盡。當之後對next(stub_generator)進行評估時,將引發StopIteration異常,因爲stub_generator現在爲空。然而


此代碼是不同的:

temp_1 = next(stub_generator) 
temp_2 = list(stub_generator) 

它將執行list(stub_generator)之前執行next(stub_generator)。意思是,當stub_generator轉換爲列表時,它仍然有一些項目。

1

作爲每language reference for assignment statements

assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression) 

賦值語句計算表達式列表(記住,這可以是單個表達式或逗號分隔的列表,後者產生的元組),並分配單個結果對象到每個目標列表,從左到右。

因此,首先評估右側的表達式。因此,list(stub_generator)首先執行,並耗盡發電機,然後你正在做next(stub_generator)試圖迭代已經耗盡的發電機。這就是爲什麼StopIteration被提出。