来源:自学PHP网 时间:2019-08-07 15:07 作者:小飞侠 阅读:次
[导读] Python中判断子串存在的性能比较及分析总结...
|
起步 对于子串搜索,Python提供了多种实现方式:in, find, index, __contains__,对其进行性能比较:
import timeit
def in_(s, other):
return other in s
def contains(s, other):
return s.__contains__(other)
def find(s, other):
return s.find(other) != -1
def index(s, other):
try:
s.index(other)
except ValueError:
return False
return True
perf_dict = {
'in:True': min(timeit.repeat(lambda: in_('superstring', 'str'))),
'in:False': min(timeit.repeat(lambda: in_('superstring', 'not'))),
'__contains__:True': min(timeit.repeat(lambda: contains('superstring', 'str'))),
'__contains__:False': min(timeit.repeat(lambda: contains('superstring', 'not'))),
'find:True': min(timeit.repeat(lambda: find('superstring', 'str'))),
'find:False': min(timeit.repeat(lambda: find('superstring', 'not'))),
'index:True': min(timeit.repeat(lambda: index('superstring', 'str'))),
'index:False': min(timeit.repeat(lambda: index('superstring', 'not'))),
}
print(perf_dict)
得到结果:
从结果上 in 的搜索方式性能上最好。 知其然也要之其所以然,下面就对于这个结果进行比较与分析。 in 与 __contains__ 比较 了解 Python 中协议的应该知道,in 操作其实也是调用 __contains__ ,但为什么 in 比 __contains__ 明显快了很多,明明它们最终调用的C语言函数是一样的。 在 CPython 中,in 属于操作符,它直接指向了 sq_contains 中的C级函数指针,而在 str 中的 sq_contains 直接指向了最终调用的C层函数。而 __contains__ 的调用方式,则需要先在 str 属性中进行 LOAD_ATTR 查找,然后再为 CALL_FUNCTION 创建函数调用所需的空间。 也就是说,in 直接指向了最终的C层函数,一步到位,也不走Python虚拟机的函数调用,而 __contains__ 调用方式先属性查找和Python函数调用的开销;所以 str.__contains__(other) 的形式要慢得多。 一般来说,in 方式更快只使用 Python 内置的C实现的类。对于用户自定义类,因为最终调用都是Python级的,所以两种方式都要对函数调用所需的空间的。 find 与 index 的比较 find 与 index 的查找方式的区别仅仅只是 index 在子串不存在时会抛出异常。从源码来看:
static PyObject *
unicode_find(PyObject *self, PyObject *args)
{
/* initialize variables to prevent gcc warning */
PyObject *substring = NULL;
Py_ssize_t start = 0;
Py_ssize_t end = 0;
Py_ssize_t result;
if (!parse_args_finds_unicode("find", args, &substring, &start, &end))
return NULL;
if (PyUnicode_READY(self) == -1)
return NULL;
result = any_find_slice(self, substring, start, end, 1);
if (result == -2)
return NULL;
return PyLong_FromSsize_t(result);
}
static PyObject *
unicode_index(PyObject *self, PyObject *args)
{
/* initialize variables to prevent gcc warning */
Py_ssize_t result;
PyObject *substring = NULL;
Py_ssize_t start = 0;
Py_ssize_t end = 0;
if (!parse_args_finds_unicode("index", args, &substring, &start, &end))
return NULL;
if (PyUnicode_READY(self) == -1)
return NULL;
result = any_find_slice(self, substring, start, end, 1);
if (result == -2)
return NULL;
if (result < 0) {
PyErr_SetString(PyExc_ValueError, "substring not found");
return NULL;
}
return PyLong_FromSsize_t(result);
}
实现方式基本相同,所以在子串存在的时候,两者的性能一致;而当子串不存在时,index 会设置异常,因此涉及异常栈的空间等异常机制,速度上也就慢了一些。 总结 in 的搜索方式性能最佳,可读性也最好,属最佳实践。 好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对自学php网的支持。 扩展阅读 https://stackoverflow.com/questions/38400370/why-in-is-faster-than-contains |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com