2024-09-26 18:12:48 发布
网友
我无意中发现,在python中,一个
string1.join(string2)
可以等价地表示为
此外,在尝试使用几个不同大小的输入timeit之后,这种奇怪的连接方式似乎快了一倍多。在
timeit
所以首先,让我们来分析一下为什么这是有效的。在
>>> string1 = "foo" >>> string2 = "bar" >>> string1.join(string2) 'bfooafoor'
这是将string1放在string2的每个项(字符)之间的操作。在
string1
string2
因此,替换空字符串有点有趣,它将空字符之间的间隔计算为空字符串,因此基本上执行相同的任务,只是在开始和结束处添加了一个额外的分隔符:
因此,将这些切片产生与str.join()相同的结果:
str.join()
>>> string2.replace('', string1)[len(string1):-len(string1)] 'bfooafoor'
显然,这个解决方案比str.join()可读性差得多,所以我总是建议不要使用它。str.join()在所有平台上都是高效的。在某些版本的Python上,替换空字符串的效率可能要低得多(我不知道是不是这样,但有可能-正如CPython中重复连接相当快,但在其他地方不一定如此)
我甚至在文档中找不到任何东西表明这种替换空字符串的行为应该是这样的,the docs for ^{}简单地说:
Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.
我看不出为什么我们应该假定字母之间的间隙应该被视为空字符串的出现(可以说,可以在字符串中的任何地方容纳无限个空字符串),因此,依赖这种行为可能是个坏主意。在
这种操作也很少见-有一个字符串序列连接在一起更常见-连接字符串的单个字符不是我个人经常要做的事情。在
有趣的是,这个x.replace("", y)似乎是the Python source中的特殊情况:
x.replace("", y)
2347 /* Algorithms for different cases of string replacement */ 2348 2349 /* len(self)>=1, from="", len(to)>=1, maxcount>=1 */ 2350 Py_LOCAL(PyStringObject *) 2351 replace_interleave(PyStringObject *self, 2352 const char *to_s, Py_ssize_t to_len, 2353 Py_ssize_t maxcount) 2354 { ...
很可能是这种特殊的套管使其性能良好。同样,由于文档中没有提到这一点,这是一个实现细节,假设它在其他Python版本中能够以同样快的速度(或者根本)工作,那将是一个错误。在
正如Lattyware所提到的,对于空字符串替换,它是一个特殊情况,replace_interleave,这是一个直接的循环,其中,源字符串和来自字符串的备用字符被复制到结果字符串。循环被编码为越快越好。在
replace_interleave
count = self_len+1; count -= 1; Py_MEMCPY(result_s, to_s, to_len); result_s += to_len; for (i=0; i<count; i++) { *result_s++ = *self_s++; Py_MEMCPY(result_s, to_s, to_len); result_s += to_len; } /* Copy the rest of the original string */ Py_MEMCPY(result_s, self_s, self_len-i);
Join方法也有一个循环,但是还有一些地方需要改进(通过我还没有找到所有方面的原因,可以按照下面的方式进行编码)和瓶颈的原因。在
如你所见,在一个循环内
上述三种操作,即使可能是串联的,也有相当大的开销。注意这也解释了为什么使用一个列表与使用字符串会有不同的结果,正如混合
同时比较两个循环
前者
最后一句话
在编写str.join时,要记住所有形式的iterable和sequences,而不仅仅是字符串,而且在没有详细说明的情况下,它很有希望的是,通用例程的执行速度可能不如为特定形式的数据提供服务的专用例程快。在
str.join
所以首先,让我们来分析一下为什么这是有效的。在
这是将
string1
放在string2
的每个项(字符)之间的操作。在因此,替换空字符串有点有趣,它将空字符之间的间隔计算为空字符串,因此基本上执行相同的任务,只是在开始和结束处添加了一个额外的分隔符:
^{pr2}$因此,将这些切片产生与
str.join()
相同的结果:显然,这个解决方案比
str.join()
可读性差得多,所以我总是建议不要使用它。str.join()
在所有平台上都是高效的。在某些版本的Python上,替换空字符串的效率可能要低得多(我不知道是不是这样,但有可能-正如CPython中重复连接相当快,但在其他地方不一定如此)我甚至在文档中找不到任何东西表明这种替换空字符串的行为应该是这样的,the docs for ^{} 简单地说:
我看不出为什么我们应该假定字母之间的间隙应该被视为空字符串的出现(可以说,可以在字符串中的任何地方容纳无限个空字符串),因此,依赖这种行为可能是个坏主意。在
这种操作也很少见-有一个字符串序列连接在一起更常见-连接字符串的单个字符不是我个人经常要做的事情。在
有趣的是,这个
x.replace("", y)
似乎是the Python source中的特殊情况:很可能是这种特殊的套管使其性能良好。同样,由于文档中没有提到这一点,这是一个实现细节,假设它在其他Python版本中能够以同样快的速度(或者根本)工作,那将是一个错误。在
正如Lattyware所提到的,对于空字符串替换,它是一个特殊情况,
replace_interleave
,这是一个直接的循环,其中,源字符串和来自字符串的备用字符被复制到结果字符串。循环被编码为越快越好。在Join方法也有一个循环,但是还有一些地方需要改进(通过我还没有找到所有方面的原因,可以按照下面的方式进行编码)和瓶颈的原因。在
^{pr2}$如你所见,在一个循环内
上述三种操作,即使可能是串联的,也有相当大的开销。注意这也解释了为什么使用一个列表与使用字符串会有不同的结果,正如混合
同时比较两个循环
前者
最后一句话
在编写
str.join
时,要记住所有形式的iterable和sequences,而不仅仅是字符串,而且在没有详细说明的情况下,它很有希望的是,通用例程的执行速度可能不如为特定形式的数据提供服务的专用例程快。在相关问题 更多 >
编程相关推荐