2013-05-08 87 views
0

考慮以下功能;懶惰評估發電機

def myfunc(): 
    a=b=c=0 
    x='12' 
    a,b,c=(i for i in x) 
    return a,b,c 

該函數拋出以下異常:ValueError:需要多於2個值才能解包。 我的意圖是將「x」變量中的可用值分配給給定順序左側的變量。因此a = 1,b = 2,c = 3,我想要做什麼。

爲了提高我對發電機的理解,我拆開功能

>>> dis.dis(myfunc) 
    2   0 LOAD_CONST    1 (0) 
       3 DUP_TOP    
       4 STORE_FAST    0 (a) 
       7 DUP_TOP    
       8 STORE_FAST    1 (b) 
      11 STORE_FAST    2 (c) 

    3   14 LOAD_CONST    2 ('12') 
      17 STORE_FAST    3 (x) 

    4   20 LOAD_CONST    3 (<code object <genexpr> at 0x297b430, file "<stdin>", line 4>) 
      23 MAKE_FUNCTION   0 
      26 LOAD_FAST    3 (x) 
      29 GET_ITER    
      30 CALL_FUNCTION   1 
      33 UNPACK_SEQUENCE   3 
      36 STORE_FAST    0 (a) 
      39 STORE_FAST    1 (b) 
      42 STORE_FAST    2 (c) 

    5   45 LOAD_FAST    0 (a) 
      48 LOAD_FAST    1 (b) 
      51 LOAD_FAST    2 (c) 
      54 BUILD_TUPLE    3 
      57 RETURN_VALUE 

我猜是UNPACK_SEQUENCE被拋出異常。在UNPACK_SEQUENCE之前可以做STORE_FAST嗎?希望我的問題有道理。

+2

'x ='12''不是''123''並且不,右手邊總是先評估 – jamylak 2013-05-08 10:31:56

回答

2

您正在使用解包分配到三個不同的變量。拆箱迭代右側的序列,以便這樣做。

UNPACK_SEQUENCE的確拋出異常,因爲你的發電機表達僅產生值,字符串'1''2',但你的左側列表中的名稱有名。

這不是發電機的問題。這是元組分配的限制,explicitly documented

a, b, c = list(x) 

拋出相同的異常,除非x是長度3,例如:

  • If the target list is a comma-separated list of targets: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

相同的錯誤將使用列表時被拋出x = '123'

您可以自由發電機表達分配給一個變量:

>>> x = '12' 
>>> a = (i for i in x) 
>>> a 
<generator object <genexpr> at 0x105046dc0> 

如果您預計c仍然設置爲0由於發電機無法提供足夠的值,那麼也不怎麼樣元組賦值工作。

你可以使用一個輔助功能爲默認設置爲:

def helper(a=0, b=0, c=0): 
    return a, b, c 

a, b, c = helper(*(i for i in x)) 

演示:

>>> def helper(a=0, b=0, c=0): 
...  return a, b, c 
... 
>>> a, b, c = helper(*(i for i in x)) 
>>> a, b, c 
('1', '2', 0) 

的輔助函數使用缺省值的所有參數,以及*調用語法使用發電機將這些視爲位置參數。

+0

我明白了,有沒有辦法產生一個解壓縮並實際分配給變量? – sardok 2013-05-08 10:37:04

+2

@sardok:你期望在這裏分配什麼?您可以只將生成器分配給左側的**一個**名稱,但應將其他兩個名稱分配給哪個名稱? – 2013-05-08 10:37:57

+0

我明白了,謝謝澄清。我意識到我正在尋找一個答案,像a,b,c = 1,2保留c的值,但是分配a和b,看起來不可能。 – sardok 2013-05-08 10:52:01