集百药草堂 發表於 2019-7-31 08:16:00

彻底搞懂Python切片操作

<p>  在利用Python解决各种实际问题的过程中,经常会遇到从某个对象中抽取部分值的情况,<strong>切片操作</strong>正是专门用于完成这一操作的有力武器。理论上而言,只要条件表达式得当,可以通过单次或多次切片操作实现任意切取目标值。切片操作的基本语法比较简单,但如果不彻底搞清楚内在逻辑,也极容易产生错误,而且这种错误有时隐蔽得比较深,难以察觉。本文通过详细例子总结归纳了切片操作的各种情况。若有错误和不足之处请大牛指正!</p>
<hr>
<h4 id="一python可切片对象的索引方式">一、Python可切片对象的索引方式</h4>
<p>Python可切片对象的索引方式包括:<strong>正索引</strong>和<strong>负索引</strong>两部分。<br>
如下图所示,以<code>a = </code>为例:<br>
<img src="https://upload-images.jianshu.io/upload_images/14029140-3da45bbfe1029df4.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/464/format/webp"></p>
<hr>
<h4 id="二python切片操作的一般方式">二、Python切片操作的一般方式</h4>
<p><strong>一个完整的切片表达式包含两个“:”,用于分隔三个参数(start_index、end_index、step),当只有一个“:”时,默认第三个参数step=1。</strong></p>
<pre><code class="language-python">切片操作基本表达式:object
</code></pre>
<p><strong>step</strong>:正负数均可,其绝对值大小决定了切取数据时的“步长”,而<strong>正负号决定了“切取方向”</strong>,正表示“从左往右”取值,负表示“从右往左”取值。当step省略时,默认为1,即从左往右以增量1取值。“<strong>切取方向非常重要</strong>!”“<strong>切取方向非常重要</strong>!”“<strong>切取方向非常重要</strong>!”,重要的事情说三遍!</p>
<p><strong>start_index</strong>:表示起始索引(包含该索引本身);该参数省略时,表示从对象“端点”开始取值,至于是从“起点”还是从“终点”开始,则由step参数的正负决定,step为正从“起点”开始,为负从“终点”开始。</p>
<p><strong>end_index</strong>:表示终止索引(不包含该索引本身);该参数省略时,表示一直取到数据”端点“,至于是到”起点“还是到”终点“,同样由step参数的正负决定,step为正时直到”终点“,为负时直到”起点“。</p>
<hr>
<h4 id="三python切片操作详细例子">三、Python切片操作详细例子</h4>
<p>以下示例均以列表a = 为例:<br>
<code>&gt;&gt;&gt; a = </code></p>
<h6 id="1切取单个值">1.切取单个值</h6>
<pre><code class="language-python">&gt;&gt;&gt; a
0
&gt;&gt;&gt; a[-4]
6
</code></pre>
<h6 id="2切取完整对象">2.切取完整对象</h6>
<pre><code class="language-python">&gt;&gt;&gt; a[:] # 从左往右

&gt;&gt;&gt; a[::] # 从左往右

&gt;&gt;&gt; a[::-1] # 从右往左

</code></pre>
<h6 id="3start_index和end_index全为正索引的情况">3.start_index和end_index全为正(+)索引的情况</h6>
<pre><code class="language-python">&gt;&gt;&gt; a # step=1,从左往右取值,start_index=1到end_index=6同样表示从左往右取值。


&gt;&gt;&gt;a # step=-1,决定了从右往左取值,而start_index=1到end_index=6决定了从左往右取值,两者矛盾。
&gt;&gt;&gt; [] # 输出为空列表,说明没取到数据。

&gt;&gt;&gt;a # step=1,决定了从左往右取值,而start_index=6到end_index=1决定了从右往左取值,两者矛盾。
&gt;&gt;&gt; [] # 同样输出为空列表。

&gt;&gt;&gt;a[:6] # step=1,从左往右取值,从“起点”开始一直取到end_index=6。
&gt;&gt;&gt;

&gt;&gt;&gt;a[:6:-1] # step=-1,从右往左取值,从“终点”开始一直取到end_index=6。
&gt;&gt;&gt;

&gt;&gt;&gt;a # step=1,从左往右取值,从start_index=6开始,一直取到“终点”。
&gt;&gt;&gt;

&gt;&gt;&gt;a # step=-1,从右往左取值,从start_index=6开始,一直取到“起点”。
&gt;&gt;&gt;
</code></pre>
<h6 id="4start_index和end_index全为负-索引的情况">4.start_index和end_index全为负(-)索引的情况</h6>
<pre><code class="language-python">&gt;&gt;&gt;a[-1:-6] # step=1,从左往右取值,而start_index=-1到end_index=-6决定了从右往左取值,两者矛盾。
&gt;&gt;&gt; []

&gt;&gt;&gt;a[-1:-6:-1] # step=-1,从右往左取值,start_index=-1到end_index=-6同样是从右往左取值。
&gt;&gt;&gt;

&gt;&gt;&gt;a[-6:-1] # step=1,从左往右取值,而start_index=-6到end_index=-1同样是从左往右取值。
&gt;&gt;&gt;

&gt;&gt;&gt;a[:-6] # step=1,从左往右取值,从“起点”开始一直取到end_index=-6。
&gt;&gt;&gt;

&gt;&gt;&gt;a[:-6:-1] # step=-1,从右往左取值,从“终点”开始一直取到end_index=-6。
&gt;&gt;&gt;

&gt;&gt;&gt;a[-6:] # step=1,从左往右取值,从start_index=-6开始,一直取到“终点”。
&gt;&gt;&gt;

&gt;&gt;&gt;a[-6::-1] # step=-1,从右往左取值,从start_index=-6开始,一直取到“起点”。
&gt;&gt;&gt;
</code></pre>
<h6 id="5start_index和end_index正负-混合索引的情况">5.start_index和end_index正(+)负(-)混合索引的情况</h6>
<pre><code class="language-python">&gt;&gt;&gt;a # start_index=1在end_index=-6的左边,因此从左往右取值,而step=1同样决定了从左往右取值。
&gt;&gt;&gt;

&gt;&gt;&gt;a # start_index=1在end_index=-6的左边,因此从左往右取值,但step=-则决定了从右往左取值,两者矛盾。
&gt;&gt;&gt; []

&gt;&gt;&gt;a[-1:6] # start_index=-1在end_index=6的右边,因此从右往左取值,但step=1则决定了从左往右取值,两者矛盾。
&gt;&gt;&gt; []

&gt;&gt;&gt;a[-1:6:-1] # start_index=-1在end_index=6的右边,因此从右往左取值,而step=-1同样决定了从右往左取值。
&gt;&gt;&gt;
</code></pre>
<h6 id="6连续切片操作">6.连续切片操作</h6>
<pre><code class="language-python">&gt;&gt;&gt;a[:8][-1:]
&gt;&gt;&gt;
</code></pre>
<p>相当于:<br>
a[:8]=<br>
a[:8]= <br>
a[:8][-1:] = 4<br>
理论上可无限次连续切片操作,只要上一次返回的依然是非空可切片对象。</p>
<h6 id="7切片操作的三个参数可以用表达式">7.切片操作的三个参数可以用表达式</h6>
<pre><code class="language-python">&gt;&gt;&gt;a # 即:a = a
&gt;&gt;&gt;
</code></pre>
<h6 id="8其他对象的切片操作">8.其他对象的切片操作</h6>
<p>前面的切片操作说明都以list为例进行说明,但实际上可进行的切片操作的数据类型还有很多,包括元组、字符串等等。</p>
<pre><code class="language-python">&gt;&gt;&gt; (0, 1, 2, 3, 4, 5)[:3] # 元组的切片操作
&gt;&gt;&gt; (0, 1, 2)

&gt;&gt;&gt;'ABCDEFG'[::2] # 字符串的切片操作
&gt;&gt;&gt;'ACEG'

&gt;&gt;&gt;for i in range(1,100)[-10:]: # 利用range函数生成1-99的整数,然后取3的倍数,再取最后十个。
       print(i, end=' ')
&gt;&gt;&gt; 72 75 78 81 84 87 90 93 96 99
</code></pre>
<hr>
<h4 id="四python常用切片操作">四、Python常用切片操作</h4>
<p>以列表:<code>a = </code>为说明对象</p>
<h6 id="1取偶数位置">1.取偶数位置</h6>
<pre><code class="language-python">&gt;&gt;&gt;b = a[::2]

</code></pre>
<h6 id="2取奇数位置">2.取奇数位置</h6>
<pre><code class="language-python">&gt;&gt;&gt;b = a

</code></pre>
<h6 id="3拷贝整个对象">3.拷贝整个对象</h6>
<pre><code class="language-python">&gt;&gt;&gt;b = a[:] # ★★★★★
&gt;&gt;&gt;print(b) #
&gt;&gt;&gt;print(id(a)) # 41946376
&gt;&gt;&gt;print(id(b)) # 41921864

&gt;&gt;&gt;b = a.copy()
&gt;&gt;&gt;print(b) #
&gt;&gt;&gt;print(id(a)) # 39783752
&gt;&gt;&gt;print(id(b)) # 39759176
</code></pre>
<p>需要注意的是:<strong>[:]和.copy()都属于“浅拷贝”,只拷贝最外层元素,内层嵌套元素则通过引用,而不是独立分配内存。</strong></p>
<pre><code class="language-python">&gt;&gt;&gt;a = ]
&gt;&gt;&gt;print('a={}'.format(a))
a=] # 原始a

&gt;&gt;&gt;b = a[:]
&gt;&gt;&gt;b = 9 # 修改b的最外层元素,将1变成9
&gt;&gt;&gt;b = 'D' # 修改b的内嵌层元素
&gt;&gt;&gt;print('a={}'.format(a)) # b修改内部元素A为D后,a中的A也变成了D,说明共享内部嵌套元素,但外部元素1没变。
a=]

&gt;&gt;&gt;print('b={}'.format(b)) # 修改后的b
b=]

&gt;&gt;&gt;print('id(a)={}'.format(id(a)))
id(a)=38669128

&gt;&gt;&gt;print('id(b)={}'.format(id(b)))
id(b)=38669192
</code></pre>
<h6 id="4修改单个元素">4.修改单个元素</h6>
<pre><code class="language-python">&gt;&gt;&gt;a = ['A','B']
, 4, 5, 6, 7, 8, 9]
</code></pre>
<h6 id="5在某个位置插入元素">5.在某个位置插入元素</h6>
<pre><code class="language-python">&gt;&gt;&gt;a = ['A','B','C']

&gt;&gt;&gt;a = ['A','B']
['A', 'B', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
</code></pre>
<h6 id="6替换一部分元素">6.替换一部分元素</h6>
<pre><code class="language-python">&gt;&gt;&gt;a = ['A','B']

</code></pre>
<hr>
<h4 id="五总结">五、总结</h4>
<p>(一)<strong>start_index、end_index、step可同为正、同为负,也可正负混合使用。但必须遵循一个原则,即两者的取值顺序必须是相同的</strong>,否则无法正确切取到数据:当start_index的位置在end_index的左边时,表示从左往右取值,此时step必须是正数(同样表示从左往右);当start_index的位置在end_index的右边时,表示从右往左取值,此时step必须是负数(同样表示从右往左)。对于特殊情况,<strong>当start_index或end_index省略时,起始索引和终止索引由step的正负来决定,不会存在取值方向出现矛盾的情况</strong>,但正和负取到的结果是完全不同的,因为一个向左一个向右。<br>
(二)在利用切片时,step的正负是必须要考虑的,尤其是当step省略时。比如<code>a[-1:]</code>,很容易就误认为是从“终点”开始一直取到“起点”,即<code>a[-1:]= </code>,但实际上<code>a[-1:]=a[-1]=9</code>,原因在于step=1表示从左往右取值,而起始索引start_index=-1本身就是对象的最右边的元素了,再往右已经没数据了,因此只有<code>a[-1]</code>一个元素。</p>
<p>&nbsp;<br>
&nbsp;<br>
&nbsp;<br>
原文经过些许修改<br>
原文作者:马尔代夫Maldives<br>
原文链接:https://www.jianshu.com/p/15715d6f4dad</p><br><br>
来源:https://www.cnblogs.com/malinqing/p/11272485.html
頁: [1]
查看完整版本: 彻底搞懂Python切片操作