A sample explanation of the subscript problem with sequence slices in python

Source: Internet
Author: User
This article mainly introduces the python in the sequence slice subscript problem related data, the article through the sample code introduced very detailed, has certain reference learning value to everybody, needs the friend to take a look below together.

Objective

In Python, a slice is a commonly used syntax, whether it is a tuple, a list, or a string, and the general syntax is:

sequence[ilow:ihigh:step] # ihigh, step may be empty; For the sake of brevity, the temporary exclusion of step usage considerations

Let's start with a simple demonstration of usage.


sequence = [1,2,3,4,5]sequence [Ilow:ihigh] # from Ilow start to ihigh-1 end sequence [Ilow:]  # from Ilow to end sequence [: Ihigh]  # Start from the head until Ihigh ends sequence [:]   # Copy the entire list

The syntax is concise and easy to understand, which is simple and useful in our daily use, but I believe that when we use this slicing grammar, we are accustomed to obeying some rules:

    • Ilow, Ihigh are less than sequece in length

    • Ilow < Ihigh

Because in most cases, only follow the above rules to get the results we expect! But what if I don't follow? What happens to the slices?

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


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

We'll call it the subscript, whether it's a tuple, a list, or a string, we can use the subscript to fetch the corresponding value, but if the subscript exceeds the length of the object, the index exception will be triggered (indexerror)


sequence = [1,2,3,4,5]print sequence[15] # # # output # # #Traceback (most recent call last): File ' test.py ', line 2, in <modul e> Print A[20]indexerror:list index out of range

So what about slices? The two grammars are very similar, assuming that my ilow and Ihigh are 10 and 20 respectively, so what's the result?

Scenario Replay


# version:python2.7a = [1, 2, 3, 5]print a[10:20] # Will the results be reported as abnormal?

See 10 and 20, completely beyond the length of the sequence A, due to the previous code, or previous experience, we always feel that this will certainly lead to a indexerror, then we open the terminal to test:


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

The result is: [], this feeling a little meaning. It's only a list. So, what about strings, tuples?


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

The results are similar to the list, and return the empty results that belong to each.

See the results of our tears fall, not to return a indexerror, but directly return to empty, which makes us think, in fact, the syntax is similar, the underlying things are certainly different, then we try to explain the results below.

Principle Analysis

Before we do that, we need to figure out how Python handles this slice, which can be assisted by the DIS module:


############# slice ################[root@iz23pynfq19z ~]# cat test.pya = [11,2,3,4]print a[20:30]  #结果: [root@iz23pynfq19z ~]# python-m dis test.py 1 0 load_const 0 (one) 3 Load_const 1 (2) 6 Load_const 2    (3) 9 Load_const 3 (4) Build_list 4 Store_name 0 (a) 2 Load_name 0 (a) load_const 4 (Load_const) 5 (+) slice+3 Print_item print_newline load_const 6 (Non e) Return_value ############# single subscript value ################[root@gitlab ~]# cat test2.pya = [11,2,3,4]print a[20] #结果: [root@ Gitlab ~]# python-m dis test2.py 1 0 load_const 0 (one) 3 Load_const 1 (2) 6 Load_const 2 (3) 9 Load_c Onst 3 (4) Build_list 4 Store_name 0 (a) 2 Load_name 0 (a) Load_const 4 (c) INARY_SUBSCR Print_item print_newline load_const 5 (None) Return_value 

In this brief introduction of the Dis module, experienced old drivers are aware that python in the interpretation of the script, there is a compilation process, the result of compiling is we often see the PYc file, which is the CodeObject object composed of byte code, and dis is to show these bytecode in a more significant way, let us see the process of execution, the following is the output column of the dis explanation:

    • The first column is the line number of the original source code.

    • The second column is the byte-code offset: Load_const on line No. 0.

    • The third column is the byte code human readable name. They were prepared for programmers.

    • The fourth column represents the parameters of the directive

    • The fifth column is the actual parameter after the calculation

The front does not repeat, is the process of reading constant variables, the main difference is: test.py Slice is the use of byte code slice+3 implementation, and test2.py single subscript value is mainly through the bytecode Binary_subscr realized, as we guessed, A similar syntax is a very different code. Because we want to expand the discussion is the slice (slice+3), so no longer expand BINARY_SUBSCR, interested in children's shoes can see the relevant source to understand the specific implementation, location: PYTHON/OBJECT/CEVAL.C

Well, let's start with the discussion under Slice+3.


/* taken from: python2.7 python/ceval.c *///First step: Pyeval_evalframeex (pyframeobject *f, int throwflag) {....//omit n lines of code Target_with _impl_noarg (SLICE, _slice) target_with_impl_noarg (slice_1, _slice) target_with_impl_noarg (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_slice (U, V, W);   Remove 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 Two: Apply_slice (Pyobject *u, Pyobject *v, Pyobject *w)/* return u[v:w] */{pytypeobject *TP = U->o   B_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))//The V object is checked again and its value is converted and saved to Ilow reTurn NULL;  if (!_pyeval_sliceindex (w, &ihigh))//Ibid. return NULL;  Return Pysequence_getslice (U, Ilow, Ihigh);  Gets 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 Three: 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) {/////////////////////////)    Sequence length makes it 0 py_ssize_t L = (*m->sq_length) (s);    if (L < 0) return NULL;    if (I1 < 0) I1 + = l;   if (I2 < 0) I2 + = l; }}//Real call to the object's Sq_slice function to perform the operation of the slice 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 code above is a bit long, the key points have been commented out, and we just need to focus on those places is enough. As above, we know that the end is going to be executed m->sq_slice(s, i1, i2) , but this sq_slice is a bit special, because different objects, which correspond to different functions, are the respective corresponding functions:


String Object stringobject.c: (Ssizessizeargfunc) String_slice,/*sq_slice*///List Object listobject.c: (ssizessizeargfunc) List_ Slice,  /* sq_slice *///tuple tupleobject.c: (ssizessizeargfunc) Tupleslice,/  * Sq_slice */

Because their three function implementations are roughly the same, we only analyze one of them, and here is a slice function analysis of the list:


/* taken 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 greater than a length, then the length of the re-assignment is  ilow = Py_size (a); if (i  High < Ilow)    Ihigh = Ilow, else if (Ihigh > Py_size (a))    //If Ihigh is greater than a length, then the length of the re-assignment is   Ihigh = Py_size (a); len = Ihigh-ilow; NP = (Pylistobject *) pylist_new (len); Creates a Ihigh-ilow new list object if (NP = = null)  return NULL; src = a->ob_item + ilow; dest = np->ob_item; for (i = 0; i < Len; i++) {    //a member in that range is added to the new List object  pyobject *v = src[i];  Py_incref (v);  Dest[i] = v; } return (Pyobject *) NP;}

Conclusion

The tile function corresponding to the Sq_slice function above can be seen, if the left and right subscripts are greater than the length of sequence, will be re-assigned to the length of sequence, so let's start with the slice: print a[10:20]< /code>, which is actually running: print A4:4 . Through this analysis, later in the encounter subscript larger than the length of the slice, should not be confused ~

Related Article

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.