2010-03-24 35 views
69

好的我愛Python的zip()函數。一直使用它,它很棒。我現在想再做一次與zip()相反的想法,認爲「我曾經知道如何做到這一點」,然後google python解壓縮,然後記住一個使用這個神奇的*來解壓縮一個壓縮的元組列表。像這樣:爲什麼x,y = zip(* zip(a,b))在Python中起作用?

x = [1,2,3] 
y = [4,5,6] 
zipped = zip(x,y) 
unzipped_x, unzipped_y = zip(*zipped) 
unzipped_x 
    Out[30]: (1, 2, 3) 
unzipped_y 
    Out[31]: (4, 5, 6) 

究竟是怎麼回事?這個神奇的星號在做什麼?還有什麼地方可以應用它,以及Python中其他令人驚歎的令人驚歎的事情對谷歌來說如此神祕又難以應付?

+2

重複:http://stackoverflow.com/questions/2233204/how-does-zipitersn-work-in-python – 2010-03-24 21:03:09

+3

噢。這正是問題,雖然,搜索stackoverflow爲'zip(*'python不會返回第一頁上的重複問題,並搜索'python *'或'python zip(*'不會返回太多,我猜是因爲'(*'被忽略了?你說得對,別人也認爲這很棒。我應該刪除這個問題嗎? – 2010-03-24 22:01:33

+1

我不會刪除它,因爲它因爲某種原因在搜索中排名較高。關閉它會允許它作爲一個重定向 – 2010-03-24 22:07:43

回答

18

星號執行apply(在Lisp和Scheme中已知)。基本上,它需要你的列表,並以該列表的內容作爲參數調用該函數。

+1

Python2系列仍然有一個'應用'功能,但我不認爲那裏是'*'無法涵蓋的任何用例。我相信它已從Python3中刪除 – 2010-03-24 21:17:15

+1

@gnibbler:已確認。 'apply'在http://www.python.org/dev/peps/pep-0361/上列出,標題爲「在Py3k中刪除的功能警告:' – MatrixFrog 2010-03-24 21:42:07

+2

僅適用,因爲星號稍後添加。 – DasIch 2010-03-27 19:21:44

8

它也是有用的多ARGS:

def foo(*args): 
    print args 

foo(1, 2, 3) # (1, 2, 3) 

# also legal 
t = (1, 2, 3) 
foo(*t) # (1, 2, 3) 

而且,你可以使用關鍵字參數和字典雙星號:

def foo(**kwargs): 
    print kwargs 

foo(a=1, b=2) # {'a': 1, 'b': 2} 

# also legal 
d = {"a": 1, "b": 2} 
foo(**d) # {'a': 1, 'b': 2} 

當然,你可以結合這些:

def foo(*args, **kwargs): 
    print args, kwargs 

foo(1, 2, a=3, b=4) # (1, 2) {'a': 3, 'b': 4} 

非常整齊有用的東西。

6

它並不總是奏效:

>>> x = [] 
>>> y = [] 
>>> zipped = zip(x, y) 
>>> unzipped_x, unzipped_y = zip(*zipped) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: need more than 0 values to unpack 

糟糕!我認爲它需要一個頭骨它嚇唬工作:

>>> unzipped_x, unzipped_y = zip(*zipped) or ([], []) 
>>> unzipped_x 
[] 
>>> unzipped_y 
[] 

在python3我想你需要

>>> unzipped_x, unzipped_y = tuple(zip(*zipped)) or ([], []) 

因爲拉鍊現在返回一個生成函數,而不是假-Y。

+0

或者只是使用一個生成器'unzipped_x =(z [0]用於z壓縮)''。如果'zipped'本身就是一個生成器,那麼首先將它轉換爲一個列表,這樣就可以再次遍歷'unzipped_y'。 'zip(* zip)'沒有額外的成本,因爲後者在解包參數的過程中也將'zipped'轉換爲列表。 – 2017-09-25 15:47:31

0

補遺@ bcherry的回答是:

>>> def f(a2,a1): 
... print a2, a1 
... 
>>> d = {'a1': 111, 'a2': 222} 
>>> f(**d) 
222 111 

因此,工程不僅僅是關鍵字參數(在this strict sense),但與命名參數太(又名位置參數)。

2

我對Python非常陌生,所以最近這讓我絆倒了我,但它必須做更多的事情,如何展示這個例子以及強調什麼。

什麼給我理解zip例子的問題是處理zip調用返回值的不對稱性。也就是說,當第一次調用zip時,返回值被分配給一個變量,從而創建一個列表引用(包含創建的元組列表)。在第二次調用中,它利用Python自動將列表(或集合?)的返回值打包爲多個變量引用的能力,每個引用都是單獨的元組。如果有人不熟悉如何在Python中工作,它會讓事情變得更容易迷失。

>>> x = [1, 2, 3] 
>>> y = "abc" 
>>> zipped = zip(x, y) 
>>> zipped 
[(1, 'a'), (2, 'b'), (3, 'c')] 
>>> z1, z2, z3 = zip(x, y) 
>>> z1 
(1, 'a') 
>>> z2 
(2, 'b') 
>>> z3 
(3, 'c') 
>>> rezipped = zip(*zipped) 
>>> rezipped 
[(1, 2, 3), ('a', 'b', 'c')] 
>>> rezipped2 = zip(z1, z2, z3) 
>>> rezipped == rezipped2 
True 
相關問題