as everyone knows , We can use index values ( Or subscript ) To find the sequence type ( Such as a string 、 list 、 Tuples …) A single element in , that , What to do if you want to get the elements of an index range ?
section (slice) It's a technique of intercepting index fragments , With the help of slicing technology , We can handle sequence type objects very flexibly . Generally speaking , The purpose of slicing is to intercept sequence objects , However , It also has some misuses and advanced usage , It's all worth our attention . therefore , This article will mainly discuss these contents with you , I hope you can learn something .
Make a statement in advance , Slicing is not exclusive to lists , But because the list is the most representative , So this article only takes the list as an example .
1、 Basic usage of slice
The list is Python A very basic and important data structure in
The writing form of slices :[i : i+n : m] ; among ,i Is the starting index value of the slice , Can be omitted when it is the first in the list ;i+n It's the end of the slice , Can be omitted when it is the last bit of the list ;m Can not provide , The default value is 1, It is not allowed to be 0 , When m When it's negative , Flip the list . Be careful : These values can be greater than the list length , Will not report crossing the border .
The basic meaning of slicing is : From the first... Of the sequence i A bit of rope causes , Take it to the right n Bit elements up to , Press m Interval filtering .
li = [1, 4, 5, 6, 7, 9, 11, 14, 16]
# All of the following can represent the entire list , among X >= len(li)
li[0:X] == li[0:] == li[:X] == li[:]
== li[::] == li[-X:X] == li[-X:]
li[1:5] == [4,5,6,7] # from 1 rise , take 5-1 Bit elements
li[1:5:2] == [4,6] # from 1 rise , take 5-1 Bit elements , Press 2 Interval filtering
li[-1:] == [16] # Take the last element
li[-4:-2] == [9, 11] # From the last four , take -2-(-4)=2 Bit elements
li[:-2] == li[-len(li):-2]
== [1,4,5,6,7,9,11] # Start from scratch , take -2-(-len(li))=7 Bit elements
# When the step size is negative , Turn the list first , Then intercept
li[::-1] == [16,14,11,9,7,6,5,4,1] # Flip the entire list
li[::-2] == [16,11,7,5,1] # Flip the entire list , Press again 2 Interval filtering
li[:-5:-1] == [16,14,11,9] # Flip the entire list , take -5-(-len(li))=4 Bit elements
li[:-5:-3] == [16,9] # Flip the entire list , take -5-(-len(li))=4 Bit elements , Press again 3 Interval filtering
# The step length of slice cannot be 0
li[::0] # Report errors (ValueError: slice step cannot be zero)
Copy code
Some of the above examples are for beginners ( Even a lot of old hands ) Come on , It may not be easy to understand . I have summed up two personal experiences :
(1) Keep the formula in mind [i : i+n : m] , When the default value appears , Complete the formula by imagination ;
(2) When the index is negative and the step size is positive , Count the index position by the reciprocal ; When the index is negative and the step size is negative , Turn over the list first , Then count the index position according to the reciprocal .
2、 Slices are pseudo independent objects
The result of the slicing operation is a new independent sequence . Take lists , After slicing the list, we get a list , Occupy new memory address .
When taking out the result of the slice , It's an independent object , therefore , It can be used for assignment operations , It can also be used in other scenarios where values are passed . however , Slicing is just a shallow copy , It copies references to elements in the original list , therefore , When there are elements of a variable length object , The new list will be subject to the original list .
li = [1, 2, 3, 4]
ls = li[::]
li == ls # True
id(li) == id(ls) # False
li.append(li[2:4]) # [1, 2, 3, 4, [3, 4]]
ls.extend(ls[2:4]) # [1, 2, 3, 4, 3, 4]
# The following example is equivalent to a judgment li Is the length greater than 8
if(li[8:]):
print("not empty")
else:
print("empty")
# The slice list is subject to the original list
lo = [1,[1,1],2,3]
lp = lo[:2] # [1, [1, 1]]
lo[1].append(1) # [1, [1, 1, 1], 2, 3]
lp # [1, [1, 1, 1]]
Copy code
Because it's visible , Take out the slice results , It can be used as a stand-alone object , But also pay attention to , Is the element of the variable length object taken out .
3、 Slices can be used as placeholders
Slices can be used as independent objects “ Take out ” The original sequence , You can also stay in the original sequence , Use as a placeholder .
Splicing methods of three formatting classes ( namely %、format()、template) Is to use the idea of placeholders . For a list , Use slices as placeholders , It can also achieve the effect of splicing list . One thing in particular to note , The value assigned to the slice must be an iteratable object .
li = [1, 2, 3, 4]
# Splicing at the head
li[:0] = [0] # [0, 1, 2, 3, 4]
# Splice at the end
li[len(li):] = [5,7] # [0, 1, 2, 3, 4, 5, 7]
# Splice in the middle
li[6:6] = [6] # [0, 1, 2, 3, 4, 5, 6, 7]
# The value assigned to the slice must be an iteratable object
li[-1:-1] = 6 # ( Report errors ,TypeError: can only assign an iterable)
li[:0] = (9,) # [9, 0, 1, 2, 3, 4, 5, 6, 7]
li[:0] = range(3) # [0, 1, 2, 9, 0, 1, 2, 3, 4, 5, 6, 7]
Copy code
In the above example , If the slice is taken out as an independent object , Then you will find that they are all empty lists , namely li[:0]==li[len(li):]==li[6:6]==[] , I call this placeholder “ Pure placeholder ”, Assign values to pure placeholders , It doesn't destroy the original elements , Only new elements will be spliced in specific index positions . When removing pure placeholders , It doesn't affect the elements in the list .
And “ Pure placeholder ” Corresponding ,“ Non pure placeholder ” The slice of is not an empty list , Operate it ( Assignment and deletion ), Will affect the original list . If pure placeholders can achieve the splicing of lists , that , Non pure placeholders can replace lists .
li = [1, 2, 3, 4]
# Replacement of different positions
li[:3] = [7,8,9] # [7, 8, 9, 4]
li[3:] = [5,6,7] # [7, 8, 9, 5, 6, 7]
li[2:4] = ['a','b'] # [7, 8, 'a', 'b', 6, 7]
# Unequal substitution
li[2:4] = [1,2,3,4] # [7, 8, 1, 2, 3, 4, 6, 7]
li[2:6] = ['a'] # [7, 8, 'a', 6, 7]
# Remove elements
del li[2:3] # [7, 8, 6, 7]
Copy code
Slice placeholders can take steps , So as to achieve the continuous spanning replacement or deletion effect . It should be noted that , This usage only supports equal length substitution .
li = [1, 2, 3, 4, 5, 6]
li[::2] = ['a','b','c'] # ['a', 2, 'b', 4, 'c', 6]
li[::2] = [0]*3 # [0, 2, 0, 4, 0, 6]
li[::2] = ['w'] # Report errors ,attempt to assign sequence of size 1 to extended slice of size 3
del li[::2] # [2, 4, 6]
Copy code
4、 Think more
Are there any other programming languages that are similar to Python The slicing operation of ? What's the difference ?
I find Go Slicing language is a strange design . First , It is a special type , That is, for the array (array) After slicing , The result is not an array ; secondly , You can create and initialize a slice , Need to declare length (len) And capacity (cap); also , It also has a dynamic mechanism that goes beyond the bounds of the underlying array and needs to be expanded , This is similar to Python The overallocation mechanism of lists has some similarities ……
in my opinion , Whatever the intention , Or writing and usage , All are Python The slicing operation is more clear and easy to use . therefore , This article will no longer compare across programming languages ( Well, , Okay, I admit it , Actually, I don't know much about other programming languages ……)
Last , There's another problem :Python What's the underlying principle of slicing ? Can we customize the slicing operation ?
The above is all the content shared this time , Want to know more python Welcome to official account :Python Programming learning circle , send out “J” Free access to , Daily dry goods sharing