了解python转置脚本
我找到了一个名为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)是什么意思?一旦完成,我们打印一个空间,我们加入该行?我只是不明白这是如何导致换位的。
任何解释将不胜感激。
fileinput
支持的文件输入的其他方法为好。它可以有效地做open(sys.argv[1],'r')
,但也支持其他可能性 - 请参阅Python documentation。你的2和3的理解是大致正确
对于每个行,行被剥离空白,然后通过空间分开。这会导致表示文件的每个由空格分隔的部分。
-
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)]
你必须把它强制到
list
为zip
返回一个迭代。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。
您的分析基本上是正确的。
注意
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
填补空白。默认fillvalue
是None
。
至于fileinput
,有些人就是觉得方便,我更喜欢with open(
...