2017-10-18 46 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( ...