179

split('\n')用来获取一个字符串中的行,发现''.split()返回一个空列表[],而''.split('\n')返回['']。这种差异有什么具体原因吗?

有没有更方便的方法来计算字符串中的行数?

4

6 回答 6

269

问题:我split('\n')用来获取一个字符串中的行,发现''.split()返回一个空列表[],而''.split('\n')返回['']

str.split()方法有两种算法。如果没有给出参数,它会在重复运行的空白处分裂。但是,如果给定参数,则将其视为单个分隔符,不会重复运行。

在拆分空字符串的情况下,第一种模式(无参数)将返回一个空列表,因为空格被吃掉并且没有值可以放入结果列表中。

相反,第二种模式(带有诸如 的参数\n)将产生第一个空字段。考虑如果你写了'\n'.split('\n'),你会得到两个字段(一个拆分,给你两半)。

问题:这种差异有什么具体原因吗?

当数据在具有可变数量空白的列中对齐时,第一种模式很有用。例如:

>>> data = '''\
Shasta      California     14,200
McKinley    Alaska         20,300
Fuji        Japan          12,400
'''
>>> for line in data.splitlines():
        print(line.split())

['Shasta', 'California', '14,200']
['McKinley', 'Alaska', '20,300']
['Fuji', 'Japan', '12,400']

第二种模式适用于分隔数据,例如CSV,其中重复的逗号表示空字段。例如:

>>> data = '''\
Guido,BDFL,,Amsterdam
Barry,FLUFL,,USA
Tim,,,USA
'''
>>> for line in data.splitlines():
        print(line.split(','))

['Guido', 'BDFL', '', 'Amsterdam']
['Barry', 'FLUFL', '', 'USA']
['Tim', '', '', 'USA']

请注意,结果字段的数量比分隔符的数量大一。想想剪断一根绳子。如果你没有剪裁,你只有一件。切一刀,出两片。进行两次切割,得到三片。Python的str.split(delimiter)方法也是如此:

>>> ''.split(',')       # No cuts
['']
>>> ','.split(',')      # One cut
['', '']
>>> ',,'.split(',')     # Two cuts
['', '', '']

问题:还有更方便的方法来计算字符串中的行数吗?

是的,有几个简单的方法。一种用途str.count(),另一种用途str.splitlines()。两种方式都会给出相同的答案,除非最后一行缺少\n. 如果缺少最后的换行符,该str.splitlines方法将给出准确的答案。一种更快且准确的技术使用 count 方法,但随后将其纠正为最终换行符:

>>> data = '''\
Line 1
Line 2
Line 3
Line 4'''

>>> data.count('\n')                               # Inaccurate
3
>>> len(data.splitlines())                         # Accurate, but slow
4
>>> data.count('\n') + (not data.endswith('\n'))   # Accurate and fast
4    

来自@Kaz 的问题:为什么将两种截然不同的算法硬塞到一个函数中?

for 的签名str.split大约有 20 年的历史,那个时代的许多 API 都是严格实用的。虽然不完美,但方法签名也不是“可怕的”。在大多数情况下,Guido 的 API 设计选择经受住了时间的考验。

当前的 API 并非没有优势。考虑以下字符串:

ps_aux_header  = 'USER               PID  %CPU %MEM      VSZ'
patient_header = 'name,age,height,weight'

当被要求将这些字符串分解为字段时,人们倾向于使用相同的英文单词“split”来描述两者。当被要求阅读诸如fields = line.split()or之类的代码时fields = line.split(','),人们倾向于将这些语句正确解释为“将一行拆分为多个字段”。

Microsoft Excel 的text-to-columns 工具做出了类似的 API 选择,并将两种拆分算法合并到同一个工具中。尽管涉及不止一种算法,但人们似乎在心理上将场分裂建模为一个单一的概念。

于 2013-05-20T08:18:51.313 回答
31

根据文档,这似乎只是它应该工作的方式:

使用指定的分隔符拆分空字符串会返回['']

如果 sep 未指定或为 None,则应用不同的拆分算法:连续空格的运行被视为单个分隔符,如果字符串具有前导或尾随空格,则结果将在开头或结尾不包含空字符串。因此,使用 None 分隔符拆分空字符串或仅包含空格的字符串将返回 []。

因此,为了更清楚起见,该split()函数实现了两种不同的拆分算法,并使用参数的存在来决定运行哪一个。这可能是因为它允许优化没有参数的参数而不是有参数的参数;我不知道。

于 2013-05-20T08:06:28.843 回答
5

.split()没有参数试图变得聪明。它会在任何空格、制表符、空格、换行符等处拆分,并且因此会跳过所有空字符串。

>>> "  fii    fbar \n bopp ".split()
['fii', 'fbar', 'bopp']

本质上,.split()不带参数用于从字符串中提取单词,而不是.split()带参数,它只接受一个字符串并将其拆分。

这就是差异的原因。

是的,通过拆分来计算行数不是一种有效的方法。计算换行的数量,如果字符串不以换行结尾,则添加一个。

于 2013-05-20T08:13:01.090 回答
2
>>> print str.split.__doc__
S.split([sep [,maxsplit]]) -> list of strings

Return a list of the words in the string S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are removed
from the result.

注意最后一句话。

要计算行数,您可以简单地计算有多少行\n

line_count = some_string.count('\n') + some_string[-1] != '\n'

最后一部分考虑了\n最后Hello, World!一行Hello, World!\n1\n.

于 2013-05-20T12:01:59.490 回答
2

使用count()

s = "Line 1\nLine2\nLine3"
n_lines = s.count('\n') + 1
于 2013-05-20T08:09:47.747 回答
0

要计算行数,您可以计算换行符的数量:

n_lines = sum(1 for s in the_string if s == "\n") + 1 # add 1 for last line

编辑

内置的另一个答案count更合适,实际上

于 2013-05-20T08:06:46.163 回答