2017-10-18 55 views
0

我找到了一個名爲transpose_file.py的Python腳本,它可以轉置空格分隔的文件。它看起來像這樣:瞭解python轉置腳本

import fileinput 

m = [] 
for line in fileinput.input(): 
    m.append(line.strip().split(" ")) 
for row in zip(*m): 
    print " ".join(row) 

我想確保我瞭解每行代碼的功能,因爲我對Python非常陌生。

1)首先,我們導入一個名爲fileinput的模塊,它允許您讀取文件並通過它們進行解析?不知道爲什麼使用簡單的開放(sys.argv中[1],「R」)爲f等是行不通的

2)請稱爲M

3)對於您輸入每行一個空列表文件,刪除行末尾的任何空格,製表符或換行符,並將空格作爲分隔符(即您的輸入文件被分隔)

4)對於每一行...不確定其餘的含義。 zip(* m)是什麼意思?一旦完成,我們打印一個空間,我們加入該行?我只是不明白這是如何導致換位的。

任何解釋將不勝感激。

回答

1
  1. fileinput支持的文件輸入的其他方法爲好。它可以有效地做open(sys.argv[1],'r'),但也支持其他可能性 - 請參閱Python documentation

  2. 你的2和3的理解是大致正確

  3. 對於每個行,行被剝離空白,然後通過空間分開。這會導致表示文件的每個由空格分隔的部分。

  4. zip(*)實際上是Python的轉置運算符。例如:

    In [1]: data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
    
    In [2]: data 
    Out[2]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
    
    In [3]: transp = list(zip(*data)) 
    
    In [4]: transp 
    Out[4]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 
    

    你必須把它強制到listzip返回一個迭代。 zip也許是較爲常用的爲「壓縮」在一起的兩個列表,以便您可以通過它們放在一起進行迭代:

    In [1]: list(zip(["one", "three", "five"], ["two", "four", "six"])) 
    Out[1]: [('one', 'two'), ('three', 'four'), ('five', 'six')] 
    

    這也是很好documented

    *運算符將網格的每個子列表分隔爲zip的單獨參數。

    " ".join在迭代每個字符串連接在一起,用空格 - 例如

    In [1]: " ".join(["foo", "bar", "baz"]) 
    Out[1]: 'foo bar baz' 
    

    這只是把空間分隔符返回到您的新換位系列串。它又是,documented

1

您的分析基本上是正確的。

注意

line.strip().split(" ") 

有點脆弱。它從行中去除所有前導空白,然後使用單個空格作爲分隔符將行分割成字符串列表。如果該行包含多個空格的運行,或者它包含製表符,則這可能無法達到您想要的效果。


zip函數迭代其並聯參數,建立從每個ARG相應項的元組。因此,首先生成所有的第一項的元組,那麼所有的第二項等

如:

for t in zip([1, 2, 3], [4, 5, 6], [7, 8, 9]): 
    print(t) 
print() 

輸出

(1, 4, 7) 
(2, 5, 8) 
(3, 6, 9) 

正如你所看到的,這個結果在換位。

我們可以使用*「圖示」操作符來序列名單傳遞給zip,在「圖示」運營商解包列表,以便zip看到每個這些序列作爲一個單獨的ARG的。

lst = [ 
    [1, 2, 3], 
    [4, 5, 6], 
    [7, 8, 9], 
] 

for t in zip(*lst): 
    print(t) 

這給出了與以前相同的輸出。

「splat」運算符不僅僅是zip的一個特殊功能:您可以在任何帶有多個參數的函數上使用它。還有「double-splat」運算符**,它將字典解壓縮爲keyword = value對。

如果序列長度不同,則zip會在最短序列中沒有剩餘項目時停止。但是,標準itertools模塊中有一個相關功能:itertools.zip_longest,其中可選fillvalue。它會一直持續下去,直到最長的序列耗盡,使用fillvalue填補空白。默認fillvalueNone


至於fileinput,有些人就是覺得方便,我更喜歡with open( ...