Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why manual string reverse is worse than slice reverse in Python 2.7? What is the algorithm being used in Slice?

Below the performance difference between Slice and manual reverse operation. If this is the case, What is the reason for that?

timeit.timeit("a[::-1]","a=[1,2,3,4,5,6]",number=100)
6.054327968740836e-05

timeit.timeit("[a[i] for i in range(len(a)-1,-1,-1)]","a=[1,2,3,4,5,6]",number=100)
0.0003132152330920235
like image 640
logeekal Avatar asked Aug 12 '14 07:08

logeekal


People also ask

What is the purpose of the reversed () method in Python?

Explanation : The reversed () returns the reversed iterator of the given string and then its elements are joined empty string separated using join (). And reversed order string is formed.

How to use string slicing in Python?

Method #2 : Using string slicing The string slicing can be used to perform this particular task, by using “-1” as the third argument in slicing we can make function perform the slicing from rear end hence proving to be a simple solution. The original string is : GeeksforGeeks The reversed sliced string is : ofskeeG

How do you slice a string backwards in Python?

Create a slice that starts at the end of the string, and moves backwards. In this particular example, the slice statement [::-1] means start at the end of the string and end at position 0, move with the step -1, negative one, which means one step backwards.

Does slicing Python lists always create copies?

Nit: "Slicing Python lists always creates copies"—except when they are assigned to, as in a [2:4] = reversed (a [2:4]) in the OP's example. People may be led to think that x = reversed (x) and x.reverse () both modify x, but they are fundamentally different operations in Python, and their results differ when x is not a variable, as shown here.


2 Answers

Here's the bytecode

from dis import dis
a = [1,2,3,4,5,6]

def func1():
    a[::-1]

def func2():
    [a[i] for i in range(len(a)-1,-1,-1)]

def func3():
    reversed(a)

In the second method, you're finding the length, creating a copy with range and creating the variable i.

bytecode

Can also use reversed to create an iterable.

bytecode2

like image 57
flau Avatar answered Oct 23 '22 15:10

flau


The slice notation for reversing a list drops down into C, which is considerably faster than a pure python implementation of a reverse. For instance, in the pure python approach the python interpreter must read, decode, and execute each instruction in the byte code, whereas the C call will be executing natively and suffer no such penalty. This penalty also extends to things such as method lookups when indexing an item and so forth, whereas in the C call there is no method, just address arithmetic. So efficient is the C implementation that it doesn't even bother with a specialised reversed slice function, and still beats the pure python implementation. Rather it creates a copy of the slice and the reverses the slice in place (done else where).

List slice code for cpython:

static PyObject *
list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
{
    PyListObject *np;
    PyObject **src, **dest;
    Py_ssize_t i, len;
    if (ilow < 0)
        ilow = 0;
    else if (ilow > Py_SIZE(a))
        ilow = Py_SIZE(a);
    if (ihigh < ilow)
        ihigh = ilow;
    else if (ihigh > Py_SIZE(a))
        ihigh = Py_SIZE(a);
    len = ihigh - ilow;
    np = (PyListObject *) PyList_New(len);
    if (np == NULL)
        return NULL;

    src = a->ob_item + ilow;
    dest = np->ob_item;
    for (i = 0; i < len; i++) {
        PyObject *v = src[i];
        Py_INCREF(v);
        dest[i] = v;
    }
    return (PyObject *)np;
}
like image 44
Dunes Avatar answered Oct 23 '22 16:10

Dunes