The subscripts of Sequence slices in Python are described in detail,

Source: Internet
Author: User

The subscripts of Sequence slices in Python are described in detail,

Preface

In python, slice is a commonly used syntax. The syntax is:

sequence[ilow:ihigh:step] # ihighStep can be empty. For the sake of simplicity, the usage of step is temporarily excluded.

Let's demonstrate the usage in a simple way.

Sequence = [1, 2, 3, 4, 5] sequence [ilow: ihigh] # Starting from ilow to ending the ihigh-1 sequence [ilow:] # Starting from ilow until the end of sequence [: ihigh] # From the beginning of the header until the end of the ihigh sequence [:] # copy the entire list

The syntax is concise and easy to understand. This syntax is simple and easy to use in our daily use, but I believe that when we use this syntax, We Will habitually follow some rules:

  • Ilow and ihigh are smaller than sequece lengths.
  • Ilow <ihigh

In most cases, only the above rules can be followed to get our expected results! But what if I do not follow it? What will happen to slice?

Whether we are using tuples, lists, or strings, when we want to take an element, we will use the following syntax:

Sequence = [1, 2, 3, 4, 5] print sequence [1] # output 2 print sequence [2] # output 3

The above 1 and 2 are called subscripts. We can retrieve the corresponding values through subscripts, whether it is tuples, lists, or strings. However, if the subscripts exceed the object length, then the index exception (IndexError) will be triggered)

Sequence = [1, 2, 3, 4, 5] print sequence [15] ### output ### Traceback (most recent call last): File "test. py ", line 2, in <module> print a [20] IndexError: list index out of range

What about slice? The two syntaxes are very similar. Suppose I ilow and ihigh are respectively 10 and 20. What is the result?

Scenario Reproduction

# Version: python2.7a = [1, 2, 3, 5] print a [] # Will the result report an exception?

We can see that 10 and 20 completely exceed the length of sequence a. Due to the previous code or previous experience, we always feel that this will certainly lead to an IndexError, let's start a terminal to test:

>>> a = [1, 2, 3, 5]>>> print a[10:20][]

The result is: [], which means that only the list can be used. What about strings and tuples?

>>> s = '23123123123'>>> print s[400:2000]''>>> t = (1, 2, 3,4)>>> print t[200: 1000]()

The results are similar to those in the list and return their own empty results.

When we see the results, our tears fall down. Instead of returning an IndexError, we directly return NULL. This reminds us that, in fact, the syntax is similar and the things behind it must be different, let's try to explain the result together.

Principle Analysis

Before unlocking the slice, let's first figure out how python processes the slice. We can use the dis module to help:

############ Slice ################ [root @ iZ23pynfq19Z ~] # Cat test. pya = [,] print a [] # result: [root @ iZ23pynfq19Z ~] # Python-m dis test. py 1 0 LOAD_CONST 0 (11) 3 LOAD_CONST 1 (2) 6 LOAD_CONST 2 (3) 9 LOAD_CONST 3 (4) 12 BUILD_LIST 4 15 STORE_NAME 0 () 2 18 LOAD_NAME 0 (a) 21 LOAD_CONST 4 (20) 24 LOAD_CONST 5 (30) 27 SLICE + 3 28 PRINT_ITEM 29 PRINT_NEWLINE 30 LOAD_CONST 6 (None) 33 RETURN_VALUE ############# single subscript value ################ [root @ gitlab ~] # Cat test2.pya = [11,2, 3,4] print a [20] # result: [root @ gitlab ~] # Python-m dis test2.py 1 0 LOAD_CONST 0 (11) 3 LOAD_CONST 1 (2) 6 LOAD_CONST 2 (3) 9 LOAD_CONST 3 (4) 12 BUILD_LIST 4 15 STORE_NAME 0 () 2 18 LOAD_NAME 0 (a) 21 LOAD_CONST 4 (20) 24 BINARY_SUBSCR 25 PRINT_ITEM 26 PRINT_NEWLINE 27 LOAD_CONST 5 (None) 30 RETURN_VALUE

In this brief introduction, experienced drivers of the dis module know that python also has a compilation process when interpreting scripts. The compilation result is the pyc file we often see, here the codeobject object consists of bytecode, and dis is to display these bytecode in a considerable way, let us see the execution process, the following is an explanation of the dis output column:

  • The first column is the number of the source code.
  • The second column is the offset of the bytecode: LOAD_CONST is in row 0th, and so on.
  • The third column is the human-readable name of the bytecode. They are prepared for programmers
  • The fourth column indicates the command parameters.
  • The Fifth Column is the calculated actual parameters.

I will not go into details earlier, that is, the process of reading constants to store variables. The main difference is: test. py slicing is implemented using the bytecode SLICE + 3, while the single subscript value of test2.py is mainly implemented using the bytecode BINARY_SUBSCR, as we guessed, similar syntaxes are completely different codes. we will discuss SLICE (SLICE + 3), so we will not expand BINARY_SUBSCR. If you are interested, you can view the relevant source code to learn about the specific implementation. Location: python/object/ceval. c

Next, let's discuss SLICE + 3.

/* From: python2.7 python/ceval. c * // Step 1: PyEval_EvalFrameEx (PyFrameObject * f, int throwflag ){.... // omit n lines of code routing (SLICE, _ slice) TARGET_WITH_IMPL_NOARG (SLICE_1, _ slice) routing (SLICE_2, _ slice) TARGET_WITH_IMPL_NOARG (SLICE_3, _ slice) _ slice: {if (opcode-SLICE) & 2) w = POP (); else w = NULL; if (opcode-SLICE) & 1) v = POP (); else v = NULL; u = TOP (); x = apply_sli Ce (u, v, w); // retrieve v: ilow, w: ihigh, and then call apply_slice Py_DECREF (u); Py_XDECREF (v); Py_XDECREF (w ); SET_TOP (x); if (x! = NULL) DISPATCH (); break ;}.... // omit n lines of code} // Step 2: apply_slice (PyObject * u, PyObject * v, PyObject * w)/* return u [v: w] */{PyTypeObject * tp = u-> ob_type; PySequenceMethods * sq = tp-> tp_as_sequence; if (sq & sq-> sq_slice & ISINDEX (v) & ISINDEX (w) {// v, w type check, to integer/long integer object Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX; if (! _ PyEval_SliceIndex (v, & ilow) // check the v object and convert the value to ilow return NULL. if (! _ PyEval_SliceIndex (w, & ihigh) // same as return NULL; return PySequence_GetSlice (u, ilow, ihigh ); // obtain the slice function corresponding to the u object} else {PyObject * slice = PySlice_New (v, w, NULL); if (slice! = NULL) {PyObject * res = PyObject_GetItem (u, slice); Py_DECREF (slice); return res;} else return NULL;} // Step 3: PySequence_GetSlice (PyObject * s, py_ssize_t i1, Py_ssize_t i2) {PySequenceMethods * m; PyMappingMethods * mp; if (! S) return null_error (); m = s-> ob_type-> tp_as_sequence; if (m & m-> sq_slice) {if (i1 <0 | i2 <0) {if (m-> sq_length) {// perform a simple initialization first. if the left and right tables are smaller, add the sequence length to classify it as 0 Py_ssize_t l = (* m-> sq_length) (s); if (l <0) return NULL; if (i1 <0) i1 + = l; if (i2 <0) i2 + = l ;}// call the sq_slice function of the object to perform the slice Operation return m-> sq_slice (s, i1, i2);} else if (mp = s-> ob_type-> tp_as_mapping) & mp-> mp_subscript ){ PyObject * res; PyObject * slice = _ PySlice_FromIndices (i1, i2); if (! Slice) return NULL; res = mp-> mp_subscript (s, slice); Py_DECREF (slice); return res;} return type_error ("'%. 200s 'object is unsliceable ", s );

Although the above Code is a little long, it is enough to note the key points, and we only need to pay attention to those points. As mentioned above, we know that the code is to be executed eventually. m->sq_slice(s, i1, i2)But this sq_slice is a bit special, because different objects correspond to different functions. Below are their corresponding functions:

// String object StringObject. c: (ssizessizeargfunc) string_slice,/* sq_slice * // list object ListObject. c: (ssizessizeargfunc) list_slice,/* sq_slice * // TupleObject. c: (ssizessizeargfunc) tupleslice,/* sq_slice */

Because the implementation of the three functions is roughly the same, we can analyze only one of them. The following is an analysis of the List slicing function:

/* From ListObject. c */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) // if ilow is longer than, then the length of a is assigned to ilow = Py_SIZE (a); if (ihigh <ilow) ihigh = ilow; else if (ihigh> Py_SIZE ()) // If ihigh is greater than the length of a, the length of a is assigned to ihigh = Py_SIZE (a); len = ihigh-ilow; np = (PyListObject *) PyList_New (len ); // create a new ihigh-ilow list object if (np = NULL) return NULL; src = a-> ob_item + ilow; dest = np-> ob_item; for (I = 0; I <len; I ++) {// Add a member in this range to the new list object PyObject * v = src [I]; py_INCREF (v); dest [I] = v;} return (PyObject *) np ;}

Conclusion

From the slice function corresponding to the sq_slice function, if slice is used, when both the left and right sides are greater than the sequence length, the sequence length will be assigned again, so we start with the slice:print a[10:20]In fact, it runs:print a4:4. Through this analysis, we will encounter slices with subscripts that are larger than the object length, so we should not be forced again ~

Well, the above is all the content of this article. I hope the content of this article will help you in your study or work. If you have any questions, you can leave a message, thank you for your support.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.