在Python中比较文件内容
我有两个文件,一个叫源文件,一个叫目标文件。我会把源文件里的每个元素和目标文件里的元素进行比较,看看源文件里的元素在目标文件里是否也存在。如果目标文件里没有这个元素,我就把它打印出来(我的最终目标是让两者之间没有差异,也就是0差异)。这是我写的代码。
def finddefaulters(source,target): f = open(source,'r') g = open(target,'r') reference = f.readlines() done = g.readlines() for i in reference: if i not in done: print i,
我需要帮助的地方有:
- 这段代码在1到10的评分中会得多少分?
- 如果文件很大,我该如何让它更好、更高效?
还有一个问题 - 当我把所有行读成列表元素时,它们被解释成'元素\n'的形式。所以为了正确比较,我必须在每个文件的末尾加一个换行符。有没有办法去掉这些换行符,这样我就不需要在文件末尾加换行符了?我试过用rstrip,但没有成功。谢谢大家的帮助。
2 个回答
一些想法:
1) 使用 [with]
来安全地打开文件:
with open(source) as f:
.............
with 语句用于将一段代码块的执行包裹在一个上下文管理器定义的方法中。这可以让我们常用的 try...except...finally 结构变得更简单,方便重复使用。
2) 你可以逐行读取文件,而不是使用 readlines:
for line in f:
..........
3) 虽然在这个短小的代码片段中可能够用,但尽量给你的变量起更有意义的名字。一个字母的名字不太推荐。
4) 如果你想利用 Python 的库,可以试试 difflib
模块里的函数。例如:
make_file(fromlines, tolines[, fromdesc][, todesc][, context][, numlines])
这个函数比较两个字符串列表(fromlines 和 tolines),并返回一个完整的 HTML 文件,其中包含一个表格,逐行显示差异,并突出显示行间和行内的变化。
关于效率:你展示的方法的运行效率是O(m*n)
,这里的m
和n
分别是reference
和done
中元素的数量。也就是说,如果你把这两个列表的大小都加倍,算法的运行时间会变成原来的4倍(还有一个固定的常数,这个对理论计算机科学家来说没什么意思)。如果m
和n
非常大,你可能需要选择一个更快的算法,比如先用.sort()
对两个列表进行排序(这个的运行效率是O(n * log(n))
),然后再遍历一次列表(运行效率是O(n)
)。这个算法的最坏情况运行效率是O(n * log(n))
,已经有了很大的改善。不过,这样做会牺牲代码的可读性和简单性,所以我建议只有在绝对必要的时候才这样做。
关于编码风格:你没有.close()
文件句柄,这是应该做的。与其打开和关闭文件句柄,不如使用Python的with
语法。还有,如果你喜欢函数式风格,可以用列表表达式替代for循环:
for i in reference:
if i not in done:
print i,
这样就变成:
items = [i.strip() for i in reference if i not in done]
print ' '.join(items)
不过,这样做的时候你在生成列表的过程中是看不到任何进度的。
正如joaquin提到的,你可以直接遍历f
,而不是用f.readlines()
,因为文件句柄支持迭代器协议。