计算除以特殊字符开头的行之外的总行数

Counting the total number of lines except the ones that start with a special character

我想从文本文件中获取原子数。这个文本文件以几行 header 开头,有时它可能会添加一些额外的信息行,这些信息行也以特殊字符开头。示例文本文件如下所示:

% site-data vn=3.0
#                        pos
Ga        0.0000000   0.0000000   0.0000000
As        0.2500000   0.2500000   0.2500000 

我的方法是计算总行数和以特殊字符开头的行数,所以这是我的尝试:

def get_atom_number():
    count = 0
    with open(sitefile,'r') as site:
        x = len(site.readlines())
        for line in site.readlines():
            if '#' in line or '%' in line:
                count +=1
return x-count

此函数的问题在于,定义了 x(总行数)后,计数器(以特殊字符开头的行数)returns 0。如果我删除该行,它作品。现在,我可以将这两个分为两个功能,但我相信这应该可以正常工作,我想知道我做错了什么。

您面临的问题是 .readlines() 在执行时消耗了整个文件。如果你再次调用它,没有任何结果,因为它已经在文件的末尾。

解决方案是先将site.readlines()赋值给一个变量,然后更改以下两行以引用该变量。这样,您只需调用一次。

def get_atom_number():
    count = 0
    with open(sitefile,'r') as site:
        lines = site.readlines()
        x = len(lines)
        for line in lines:
            if '#' in line or '%' in line:
                count +=1
    return x - count

if '#' in line or '%' in line: 将检查字符是否在行中的任何位置。使用 startswith 代替·

if line.startswith(('#', '%')):

现在关于计数的方法,也可以只在不是行开头的字符才加计数,不需要知道总数提前行,不需要消耗所有行:

if not line.startswith(('#', '%')):
    counter += 1

那你可以直接在最后打印计数器

完整代码:

def get_atom_number():
    count = 0
    with open(sitefile,'r') as site:
        for line in site.readlines():
            if not line.startswith(('#', '%')):
                count +=1
    return count

改用readline

def get_atom_number():
    count = 0
    with open(sitefile,'r') as site:
        for line in site.readline():
            if '#' not in line and '%' not in line:
                count +=1
    return count

作为mozway的回答,startswith是一个更好的解决方案,所以代码可以这样:

from pathlib import Path
from typing import Union

IGNORE = ('#', '%')

def get_atom_number(filename: str = sitefile, ignore_chars: Union[str, tuple] = IGNORE) -> int:
    '''Count how many lines in filename that not startswith ignore_chars'''
    return len([1 for i in Path(filename).read_text().splitlines() if not i.startswith(ignore_chars)])

第 4 行代码中的第一个调用 site.readlines() 将文件光标移动到末尾。所以第 5 行的第二次调用 site.readlines() 只得到一个空列表。 您可以试试下面的代码,它将调用 site.readlines() 的结果保存到变量 lines 中。我认为它会解决您的问题。

def get_atom_number():
    count = 0
    with open(sitefile,'r') as site:
        lines = site.readlines()
        x = len(lines)
        for line in lines:
            if '#' in line or '%' in line:
                count +=1
    return x - count