考虑一条python线:
str[::-1]
我发现它非常快,并且比某些 O(n)解决方案更快,也节省了内存。在这种情况下,Python使用什么算法?
答案 0 :(得分:3)
In [1]: import time
In [2]: def reverse_list_time(my_list):
...: start = time.time()
...: reversed = my_list[::-1]
...: stop = time.time()
...: return stop - start
...:
In [3]: reverse_list_time(list(range(1000)))
Out[3]: 1.33514404296875e-05
In [4]: testing_lists = (list(range(n)) for n in range(1000,100000,500))
In [5]: testing_lists
Out[5]: <generator object <genexpr> at 0x7f7786bd97d8>
In [6]: results = list(map(reverse_list_time,testing_lists))
这是我的结果
对我来说,这看起来大致是O(n)。
如果这并不能说服你,那么这里就是the implementation。对我来说,它看起来像是一个非常直接的O(n)解决方案。这是它的核心:
else {
result = PyList_New(slicelength);
if (!result) return NULL;
src = self->ob_item;
dest = ((PyListObject *)result)->ob_item;
for (cur = start, i = 0; i < slicelength;
cur += step, i++) {
it = src[cur];
Py_INCREF(it);
dest[i] = it;
}
return result;
答案 1 :(得分:2)
您可以使用Python的dis.dis
模块来反汇编str[::-1]
:
>>> import dis
>>> def reverse_(str_):
... return str_[::-1]
...
>>> dis.dis(reverse_)
6 0 LOAD_FAST 0 (str_)
3 LOAD_CONST 0 (None)
6 LOAD_CONST 0 (None)
9 LOAD_CONST 1 (-1)
12 BUILD_SLICE 3
15 BINARY_SUBSCR
16 RETURN_VALUE
您可以在documentation中查看每条指令的含义。对于LOAD_FAST
,文档说:
将对本地
co_varnames[var_num]
的引用推送到堆栈。
co_varnames
是一个始终与代码对象一起出现的结构。在这种情况下,它是str_
:
>>> reverse_.__code__.co_varnames
('str_',)
下一条指令LOAD_CONST
的描述如下:
将
co_consts[consti]
推入堆栈。
推入堆栈的值为None
(dis
很有帮助,并为您查找)。接下来的两条指令是LOAD_CONST
指令,用于将值None
和-1
推送到堆栈。
下一条指令BUILD_SLICE
被描述为:
将切片对象推送到堆栈上。 argc必须是2或3.如果是2,则推送
slice(TOS1, TOS)
;如果是3,则推送slice(TOS2, TOS1, TOS)
。有关详细信息,请参阅slice()
内置函数。
TOS2, TOS1, TOS
表示堆栈None, None, -1
上的值,这些值从堆栈推送到slice()
对象(对象变为slice(None, None, -1)
)。
BINARY_SUBSCR
被描述为:
实施
TOS = TOS1[TOS]
。
这意味着Python计算str_[sli]
,其中sli
是在前一条指令中推送到堆栈的slice()
对象。
>>> str_[slice(None, None, -1)]
最后,RETURN_VALUE
:
使用TOS返回函数的调用者。
最后一条指令返回上一步的结果,即反转str_
。
实际上,通过切片反转列表涉及比Python中的其他反转方法更多的内存开销。长话短说(并且没有长长的兔子洞),因为切片操作返回整个列表,所以会发生更大的内存开销。我认为它非常快,并且比某些O(n)解决方案更快,也节省了内存。
一种替代方法可能是:使用reversed()
生成迭代器,这通常对内存和时间更有效(尽管从此迭代器生成列表非常耗时)。
在这种情况下,Python使用什么算法?
简而言之:Python加载变量str
,构建slice(None, None, -1)
对象,实现str[slice(None, None, -1)]
(source code),并返回反转的{{1} }}