2017-06-29 29 views
2

當使用一個函數返回一個元組的多個值時,我經常會發現自己使用以下習慣用法從列表理解中解壓縮結果。通過空輸入從列表理解開箱Python

fiz, buz = zip(*[f(x) for x in input]) 

大部分能正常工作的時間,但它拋出一個ValueError: need more than 0 values to unpack如果input是空的。這兩種方式我能想到的解決這個問題是

fiz = [] 
buz = [] 
for x in input: 
    a, b = f(x) 
    fiz.append(a) 
    buz.append(b) 

if input: 
    fiz, buz = zip(*[f(x) for x in input]) 
else: 
    fiz, buz = [], [] 

但這兩種感覺格外Python化,前者是過於冗長,如果輸入的是後者無法正常工作一個生成器而不是一個列表(除了需要一個if/else之外,我覺得應該不需要)。

有沒有一個很好的簡單方法來做到這一點?我最近一直在Python 2.7中工作,但如果他們不同,他們也會很有興趣瞭解任何Python 3解決方案。

回答

0

我會考慮使用collections.namedtuple()這種事情。我相信命名的元組被認爲更加pythonic,並且應該避免需要複雜的列表解析和壓縮/解壓縮。


documentation

>>> p = Point(11, y=22)  # instantiate with positional or keyword arguments 
>>> p[0] + p[1]    # indexable like the plain tuple (11, 22) 
33 
>>> x, y = p    # unpack like a regular tuple 
>>> x, y 
(11, 22) 
>>> p.x + p.y    # fields also accessible by name 
33 
>>> p      # readable __repr__ with a name=value style 
Point(x=11, y=22) 
+0

我熟悉'namedtuple's,但我不明白他們在這裏會有什麼幫助。通常,當我做這樣的事情時,'fiz'和'buz'將是兩個單獨的事情,它們可以方便地或一起計算,但是一旦解包就會分開處理。 – Nyle

0

你可以使用:

fiz = [] 
buz = [] 
results = [fiz, buz] 

for x in input: 
    list(map(lambda res, val: res.append(val), results, f(x))) 

print(results) 

備註名單(圖(...)):在Python3,地圖返回發電機,所以如果我們希望lambda被執行,我們必須使用它。

(摘自我的回答對Pythonic way to append output of function to several lists,在那裏你可以找到其他的想法。)

0

如果f = lambda x: (x,x**2)那麼這個工程

x,y = zip(*map(f,input)) if len(input) else ((),()) 

如果input=[]x=() and y=()

如果input=[2]x=(2,) and y=(4,)

如果input=[2,3]x=(2,3) and y=(4,9)

他們的元組(未列出),但是那那很容易改變。