假设我想编写一个不使用split
函数即可反转句子中单词的函数。这是一种可能的解决方案:
def reverse_words_1(s):
i, n, r = 0, len(s), []
while i < n:
while i < n and s[i] == ' ': i += 1
if i == n: break
p = i
while i < n and s[i] != ' ': i += 1
# Instead of appending here and then reversing after the while
# loop is done, we could r.insert(0, ..). But insert is much
# slower than append/reverse because insert always requires that
# each pointer in the list must be copied and moved. Whereas
# append only requires copying if there isn't enough space for
# the new element in the currently allocated memory block.
# Helpful explanations:
# https://stackoverflow.com/questions/7776938/python-insert-vs-append
# https://bytes.com/topic/python/answers/34036-timing-difference-insert-vs-append-reverse
r.append( s[p : i] )
r.reverse()
return ' '.join(r)
我的代码中的注释指出insert
比append/reverse
慢得多。但是我的评论实际上仅比较了insert
和append
采取的行动。我的评论未涉及reverse
的动作或速度。
那么reverse
在CPython中如何工作?我的猜测是reverse
正在重新指向列表中的指针。像这样:
def reverse(lst):
l, r = 0, len(lst) - 1
while l < r:
lst[l], lst[r] = lst[r], lst[l]
l += 1
r -= 1
这是CPython在内部执行reverse
函数的大致方式吗?
如果我对reverse
的工作方式的猜测是正确的,那么我想重新指向指针比复制和移动指针要快得多?
答案 0 :(得分:1)
或多或少是listobject.c中代码的工作方式。下面的代码反转切片,但是reverse方法使用整个列表调用该切片。
/* Reverse a slice of a list in place, from lo up to (exclusive) hi. */
static void
reverse_slice(PyObject **lo, PyObject **hi)
{
assert(lo && hi);
--hi;
while (lo < hi) {
PyObject *t = *lo;
*lo = *hi;
*hi = t;
++lo;
--hi;
}
}