[英]How does Python implement str[::-1]?
Consider a python line: 考虑一条python行:
str[::-1]
I see it's very fast, and way more faster than some O(n) solution and also memory saving. 我看到它非常快,并且比某些O(n)解决方案要快得多,并且还节省了内存。 What algorithm does Python use in this case?
在这种情况下,Python使用什么算法?
Hmm, have you tried any quick-and-dirty tests? 嗯,您是否尝试过任何快速和肮脏的测试? Here is a first-pass:
这是第一次通过:
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))
And here are my results 这是我的结果
That looks roughly O(n) to me. 在我看来,这大概是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;
You can use Python's dis.dis
module to disassemble str[::-1]
: 您可以使用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
You can see what each instruction means in the documentation . 您可以在文档中查看每个说明的含义。 For
LOAD_FAST
the docs say: 对于
LOAD_FAST
,文档说:
Pushes a reference to the local
co_varnames[var_num]
onto the stack.将对本地
co_varnames[var_num]
的引用co_varnames[var_num]
入堆栈。
co_varnames
is a structure that is always present with a code object. co_varnames
是代码对象始终存在的结构。 In this case, it is str_
: 在这种情况下,它是
str_
:
>>> reverse_.__code__.co_varnames
('str_',)
The next instruction, LOAD_CONST
, is described like this: 下一条指令
LOAD_CONST
的描述如下:
Pushes
co_consts[consti]
onto the stack.将
co_consts[consti]
入堆栈。
The value that was pushed onto the stack is None
( dis
is helpful and looked it up for you). 被压入堆栈的值是
None
( dis
会有所帮助,并会为您查找)。 The next two instructions are LOAD_CONST
instructions that push the values None
and -1
onto the stack. 接下来的两条指令是
LOAD_CONST
指令,它们将值None
和-1
推入堆栈。
The next instruction, BUILD_SLICE
, is described as: 下一条指令
BUILD_SLICE
描述为:
Pushes a slice object on the stack.
将切片对象压入堆栈。 argc must be 2 or 3. If it is 2,
slice(TOS1, TOS)
is pushed;argc必须为2或3。如果为2,
slice(TOS1, TOS)
压入; if it is 3,slice(TOS2, TOS1, TOS)
is pushed.如果为3,则
slice(TOS2, TOS1, TOS)
被压入。 See theslice()
built-in function for more information.有关更多信息,请参见
slice()
内置函数。
TOS2, TOS1, TOS
represent the values on the stack None, None, -1
, which are pushed to the slice()
object from the stack (the object becomes slice(None, None, -1)
). TOS2, TOS1, TOS
表示堆栈None, None, -1
上的值,这些值从堆栈推送到slice()
对象(对象变为slice(None, None, -1)
)。
BINARY_SUBSCR
is described as: BINARY_SUBSCR
被描述为:
Implements
TOS = TOS1[TOS]
.实现
TOS = TOS1[TOS]
。
This means that Python computes str_[sli]
where sli
is the slice()
object pushed to the stack in the previous instruction. 这意味着Python将计算
str_[sli]
,其中sli
是上sli
指令中压入堆栈的slice()
对象。 It's the equivalent of 相当于
>>> str_[slice(None, None, -1)]
Finally, RETURN_VALUE
: 最后,
RETURN_VALUE
:
Returns with TOS to the caller of the function.
与TOS一起返回给函数的调用者。
The last instruction returns the result of the previous step, which is the reversed str_
. 最后一条指令返回上一步的结果,即反向的
str_
。
I see it's very fast, and way more faster than some O(n) solution and also memory saving.
我看到它非常快,并且比某些O(n)解决方案要快得多,并且还节省了内存。
In fact, reversing a list by slicing involves more memory overhead than some other reversal methods in Python. 实际上,与Python中的某些其他逆转方法相比,通过切片逆转列表涉及更多的内存开销。 Long story short (and without going down a long rabbit hole), the greater memory overhead occurs because the slicing operation returns a whole list.
长话短说(并且不会陷入漫长的兔子洞),因为切片操作会返回整个列表,所以会产生更大的内存开销。
One alternative method might be: generating an iterator using reversed()
, which is usually more performant for memory and time (although, generating a list from this iterator is time-consuming). 一种替代方法可能是:使用
reversed()
生成迭代器,这通常在内存和时间方面表现更好(尽管从此迭代器生成列表很耗时)。
What algorithm does Python use in this case?
在这种情况下,Python使用什么算法?
To make a long story short: Python loads the variable str
, builds a slice(None, None, -1)
object, implements str[slice(None, None, -1)]
( source code ), and returns the reversed str
. 简而言之:Python加载变量
str
,构建slice(None, None, -1)
对象,实现str[slice(None, None, -1)]
( 源代码 ),并返回相反的str
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.