简而言之:
这是因为针对两种不同情况存在两个函数,可以在unicode_strip
中看到;do_strip
和_PyUnicodeXStrip
,前者执行速度比后者快得多。
函数do_strip
用于普通情况下的str.strip()
,即没有参数的情况,而do_argstrip
(它包装了_PyUnicode_XStrip
)用于调用str.strip(arg)
时提供参数的情况。
do_argstrip
只检查分隔符,如果它是有效的并且不等于 None
(在这种情况下调用do_strip
),则调用 _PyUnicode_XStrip
。
do_strip
和 _PyUnicode_XStrip
遵循相同的逻辑,使用两个计数器,一个为零,另一个为字符串的长度。
使用两个while
循环,第一个计数器递增,直到达到一个不等于分隔符的值,第二个计数器递减,直到满足相同的条件。
区别在于执行当前字符是否不等于分隔符的方式。
对于 do_strip
:
在字符串中的字符可以表示为ascii
的最常见情况下,会出现额外的小性能提升。
while (i < len) {
Py_UCS1 ch = data[i];
if (!_Py_ascii_whitespace[ch])
break;
i++;
}
因此,简而言之,它相当有效。
如果字符不在ascii
范围内,则差异并不那么明显,但它们确实会减缓整体执行速度:
while (i < len) {
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
if (!Py_UNICODE_ISSPACE(ch))
break;
i++;
}
对于_PyUnicodeXStrip
:
在这种情况下,访问底层数据与前面的情况一样,使用PyUnicode_Read
;然而,检查字符是否为空格(或者实际上是我们提供的任何字符)要复杂得多。
while (i < len) {
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
if (!BLOOM(sepmask, ch))
break;
if (PyUnicode_FindChar(sepobj, ch, 0, seplen, 1) < 0)
break;
i++;
}
PyUnicode_FindChar
被使用,虽然效率高,但与数组访问相比要复杂得多且速度较慢。对于字符串中的每个字符,它都会被调用以查看该字符是否包含在我们提供的分隔符中。随着字符串长度的增加,不断调用此函数所引入的开销也会增加。
对于那些感兴趣的人,
PyUnicode_FindChar
在进行相当多的检查后,最终会在
stringlib
中调用
find_char
,在分隔符的长度小于 10 的情况下,将一直循环直到找到该字符。
除此之外,还需要考虑已经需要调用的其他附加函数。
关于
lstrip
和
rstrip
,情况类似。存在用于执行剥离模式的标志,即:对于
rstrip
,有
RIGHTSTRIP
;对于
lstrip
,有
LEFTSTRIP
;对于
strip
,有
BOTHSTRIP
。在
do_strip
和
_PyUnicode_XStrip
内部的逻辑是基于标志条件性地执行的。
strip(' ')
来节省时间,因为它不需要去除所有的空白字符,只需去除空格字符即可。 - undefined