内容简介:对于子串搜索,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:True': 0.2763608000000001,
'in:False': 0.2794432,
'__contains__:True': 0.40546490000000013,
'__contains__:False': 0.4122471000000001,
'find:True': 0.497128,
'find:False': 0.4951530000000002,
'index:True': 0.5243821999999998,
'index:False': 0.8693923999999988
}
从结果上 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
会设置异常,因此涉及异常栈的空间等异常机制,速度上也就慢了一些。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【Java必修课】判断String是否包含子串的四种方法及性能对比
- 你有没有想过: Java 虚拟机是如何判断两个对象是否相同的?判断的流程是什么?
- iOS Rotation 判断
- 判断是否是闰年
- 数值类型(金额)限制与判断
- ansible笔记(26):条件判断
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ARKit for iPhone and iPad
Wallace Wang / Apress / 2018-11-5 / USD 39.99
Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
JSON 在线解析
在线 JSON 格式化工具