计算 python 中的非空白行和行长总和

Counting non blank and sum of length of lines in python

我正在尝试创建一个函数,它接受一个文件名,它 returns 一个二元组,其中包含该程序中非空行的数量,以及所有这些行的长度之和。这是我当前的程序。我做了一个尝试并得到了以下代码:

def code_metric(file_name):
    with open(file_name) as f:
        lines = f.read().splitlines()
    char_count = sum(map(len,(map(str.strip,filter(None,lines)))))
    return len(lines), char_count

我应该为此使用函数映射、过滤和缩减。我之前曾问过这个问题并改进了我的答案,但它仍然给我一个错误。这里是 link 之前版本的问题:

当我运行文件cmtest.py有以下内容

import prompt,math

x = prompt.for_int('Enter x')
print(x,'!=',math.factorial(x),sep='')

结果应该是

(3,85)

但我不断得到:

(4,85)

要测试的另一个文件colltaz.py例如:

结果应该是:

(73, 2856)

位我不断得到:

(59, 2796)

这是 collatz.py 文件的 link:

Collatz.py file link 任何人都可以帮助我更正代码。我是 python 的新手,如果有任何帮助,我们将不胜感激。

试试这个:

def code_metric(file_name):
    with open(file_name) as f:
        lines = [line.rstrip() for line in f.readlines()]
    nonblanklines = [line for line in lines if line]
    return len(nonblanklines), sum(len(line) for line in nonblanklines)

示例:

>>> code_metric('collatz.py')
(73, 2856)

>>> code_metric('cmtest.py')
(3, 85)

讨论

我只能通过删除行尾的尾随换行符和尾随空格来实现 collatz.py 的预期结果。这是在这一步完成的:

lines = [line.rstrip() for line in f.readlines()]

下一步是删除空行:

nonblanklines = [line for line in lines if line]

我们要return非空行的数量:

len(nonblanklines)

我们还要return非空行的总字符数:

sum(len(line) for line in nonblanklines)

大文件的备用版本

此版本不需要将文件一次性全部保存在内存中:

def code_metric2(file_name):
    with open(file_name) as f:
        lengths = [len(line) for line in (line.rstrip() for line in f.readlines()) if line]
    return len(lengths), sum(lengths)

使用 reduce

的替代版本

Python 的创建者 Guido van Rossum,wrote this 关于 reduce 内置:

So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.

因此 reduceno longer a builtin in python3。但是,为了兼容性,它在 functools 模块中仍然可用。下面的代码如何 reduce 可用于此特定问题:

from functools import reduce

def code_metric3(file_name):
    with open(file_name) as f:
        lengths = [len(line) for line in (line.rstrip() for line in f.readlines()) if line]
    return len(lengths), reduce(lambda x, y: x+y, lengths)

这是另一个更大量使用 reduce 的版本:

from functools import reduce
def code_metric4(file_name):
    def fn(prior, line):
        nlines, length = prior
        line = line.rstrip()
        if line:
            nlines += 1
            length += len(line)
        return nlines, length
    with open(file_name) as f:
        nlines, length = reduce(fn, f.readlines(), (0, 0))
    return nlines, length