python 中的序列

ARM的程式設計師敲著詩歌的夢發表於2019-01-13

python 中的序列

序列概述

Python 內建了多種序列,比如列表、元組和字串。

列表和元組的主要不同在於:列表是可以修改的,而元組不可以。

在需要處理一系列值時,序列很有用。在資料庫中,你可能使用序列來表示人,其中第一個元素為姓名,第二個元素為年齡。如果使用列表來表示,將類似於下面這樣:

>>> edward = ['Edward Gumby', 42] 

要點是:所有元素都放在方括號內,並用逗號隔開。

有的人喜歡把列表看成是 C 語言中的陣列。它們確實有相似性,但請你注意:C 語言中的陣列都是相同型別的元素,而 Python 的列表可以是不同型別的元素。

序列內還可以包含其他序列,比如:

>>> edward = ['Edward Gumby', 42] 
>>> john = ['John Smith', 50] 
>>> database = [edward, john] 
>>> database 
[['Edward Gumby', 42], ['John Smith', 50]] 

注意

Python支援一種資料結構的基本概念,叫做“容器”(container)。容器基本上就是可包含其他物件的物件。兩種主要的容器是序列(如列表和元組)和對映(如字典)。在序列中,每個元素都有編號,而在對映中,每個元素都有鍵。有一種既不是序列也不是對映的容器,它就是集合(set)。

通用的序列操作

有幾種操作適用於所有序列,這些操作是索引、切片、相加、相乘、成員資格檢查和迭代等。另外,Python 還提供了一些內建函式,可用於確定序列的長度以及找出序列中最大和最小的元素。

索引(indexing)

序列中的所有元素都有編號——從0開始遞增。你可像下面這樣使用編號來訪問各個元素:

>>> greeting = 'Hello' 
>>> greeting[0] 
'H' 

其實這和 C 語言中的字串很像。

字串就是由字元組成的序列。索引0指向第一個元素,這裡為字母H。不同於其他一些語言,Python 沒有專門用於表示字元的型別,因此一個字元就是隻包含一個元素的字串。

當你使用負數索引時,Python 將從右(即從最後一個元素)開始往左數,因此 -1 是最後一個元素的位置。

>>> greeting[-1] 
'o' 

對於字串字面量(以及其他的序列字面量),可直接對其執行索引操作,無需先將其賦給變數。

>>> 'Hello'[1] 
'e' 

其實在 C 語言中也可以這樣,比如:

#include <stdio.h>

int main(void)
{
    printf("%c\r\n", "HelloWorld"[1]);
    return 0;
}

以上這段程式碼的執行結果是:

e

如果函式呼叫返回一個序列,可直接對其執行索引操作。例如,如果你只想獲取使用者輸入的年份的第4位,可這樣做:

In [3]: fourth = input("Year : ")[3]
Year : 1998

In [4]: fourth
Out[4]: '8'

以上操作是在 ipython 中演示的,ipython 是什麼呢?

IPython provides a rich architecture for interactive computing with:

  • A powerful interactive shell.
  • A kernel for Jupyter.
  • Support for interactive data visualization and use of GUI toolkits.
  • Flexible, embeddable interpreters to load into your own projects.
  • Easy to use, high performance tools for parallel computing.

​ —— 摘自 https://ipython.org/

切片(slicing)

除了使用索引來訪問單個元素外,還可使用切片(slicing)來訪問特定範圍內的元素。為此,可使用兩個索引,並用冒號分隔,比如

In [5]: nums=[1,2,3,4,5,6,7,8,9,10]

In [6]: nums[3:6]
Out[6]: [4, 5, 6]

In [7]: nums[0:1]
Out[7]: [1]

注意:第一個索引是包含的第一個元素的編號,但第二個索引是切片後餘下的第一個元素的編號。

簡而言之,你提供兩個索引來指定切片的邊界,其中第一個索引指定的元素包含在切片內,但第二個索引指定的元素不包含在切片內。

利用簡寫

假設你要訪問前述列表 nums 中的最後三個元素,可以這樣寫:

>>> nums[7:10] 
[8, 9, 10] 

在這裡,索引10指的是第11個元素,雖然它並不存在,但確實是到達最後一個元素後再前進一步的位置。

切片中也可使用負數索引。

>>> nums[-3:-1] 
[8, 9] 

然而,這樣好像無法包含最後一個元素。如果使用索引0,即到達列表末尾後再前進一步所處的位置,結果將如何呢?

在 ipython 中的結果如下:

In [5]: nums[-3:0]
Out[5]: []

結果並不是你想要的。事實上,執行切片操作時,如果第一個索引指定的元素位於第二個索引指定的元素後面(在這裡,倒數第3個元素位於第1個元素後面),結果就為空序列。

還好,我們可以使用一種簡寫:如果切片結束於序列末尾,可省略第二個索引。

In [6]: nums[-3:]
Out[6]: [8, 9, 10]

同理,如果切片始於序列開頭,可省略第一個索引。

In [7]: nums[:3]
Out[7]: [1, 2, 3]

要複製整個序列,可將兩個索引都省略,在方括號內只留一個冒號。

In [8]: nums[:]
Out[8]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

步長

執行切片操作時,你顯式或隱式地指定起點和終點,但通常省略了另一個引數,即步長。預設步長為1。這意味著從一個元素移到下一個元素,因此切片包含起點和終點之間的所有元素。

In [9]: nums[0:10:1]
Out[9]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

如果指定的步長大於1,將跳過一些元素。例如,步長為2時,將從起點和終點之間每隔一個元素提取一個元素。

In [10]: nums[0:10:2]
Out[10]: [1, 3, 5, 7, 9]
    
In [11]: nums[0:10:3]
Out[11]: [1, 4, 7, 10]

顯式地指定步長時,也可使用前述簡寫。例如,要從序列中每隔3個元素提取1個,只需提供步長4即可。

In [12]: nums[::4]
Out[12]: [1, 5, 9]

當然,步長不能為0,否則無法向前移動。

In [14]: nums[1:7:0]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-7219eb36c975> in <module>()
----> 1 nums[1:7:0]

ValueError: slice step cannot be zero

步長可以為負數,即從右向左提取元素。

In [15]: nums[::-1]
Out[15]: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
In [16]: nums[10:0:-2]
Out[16]: [10, 8, 6, 4, 2]

上面的結果,有人會疑惑。他這樣想:從10開始,也就是第11個元素,即最後一個元素的後面,然後向左走2步,應該是9,7,5,3,1 才對。

開始我也挺疑惑的,後來才明白,因為沒有10,最多是9,所以這裡的10就相當於9。

In [19]: nums[9:0:-2]
Out[19]: [10, 8, 6, 4, 2]
In [20]: nums[0:10:-2]
Out[20]: []

上面這個結果又是為什麼呢?

步長為負數時,第一個索引必須比第二個索引大。步長為正表示從左向右走,為負表示從右向左走。想象有一個數軸,從0向左走,是走不到10的,所以結果為空。

In [22]: nums[::-2]
Out[22]: [10, 8, 6, 4, 2]

當省略起始和結束索引時,Python 竟然執行了正確的操作:步長為正數時,它從起點移到終點,而步長為負數時,它從終點移到起點。

In [23]: nums
Out[23]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In [24]: nums[:5:-2]
Out[24]: [10, 8]

In [25]: nums[5::-2]
Out[25]: [6, 4, 2]

請看第4行,省略的索引,到底是左邊的起點還是右邊的終點呢?因為步長是負數,所以一定是從右往左走,所以省略的是右邊的10;

第7行,因為步長為負數,所以應該從右向左,所以省略的索引是0;

In [26]: nums[10:5:-2]
Out[26]: [10, 8]

In [27]: nums[5:0:-2]
Out[27]: [6, 4, 2]

可以看到,和之前的結果是一樣的。

序列相加

可使用加法運算子來拼接序列。

In [28]: [1,2,3]+[4,5,6,7]
Out[28]: [1, 2, 3, 4, 5, 6, 7]

In [29]: "hello"+" "+"world"
Out[29]: 'hello world'

一般而言,不能拼接不同型別的序列。

In [30]: [1,2,3]+"hello"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-30-9346ef22b4d4> in <module>()
----> 1 [1,2,3]+"hello"

TypeError: can only concatenate list (not "str") to list

乘法

將序列與數 N 相乘時,將重複這個序列 N 次來建立一個新序列:

In [31]: "H"*6
Out[31]: 'HHHHHH'

In [32]: 10*"Hello"
Out[32]: 'HelloHelloHelloHelloHelloHelloHelloHelloHelloHello'

In [34]: [32,1]*3
Out[34]: [32, 1, 32, 1, 32, 1]

None、空列表和初始化

空列表是使用不包含任何內容的兩個方括號表示的。

In [43]: list=[]

In [44]: list
Out[44]: []

如果要建立一個可包含10個元素的列表,但沒有任何有用的內容,你可以使用[0]*10,這將建立一個包含10個零的列表。然而,在有些情況下,你可能想使用表示“什麼都沒有”的值,在這種情況下,可使用 None。在Python中,None表示什麼都沒有。因此,要將列表的長度初始化為10,可像下面這樣做:

In [35]: seq=[None]*10

In [36]: seq
Out[36]: [None, None, None, None, None, None, None, None, None, None]

成員資格

要檢查特定的值是否包含在序列中,可使用運算子in。它檢查是否滿足指定的條件,並返回相應的值:滿足時返回True,不滿足時返回False。這樣的運算子稱為布林運算子,而前述真值稱為布林值。

下面是一些例子。

In [48]: permission='rw'

In [49]: 'w' in permission
Out[49]: True

In [50]: 'x' in permission
Out[50]: False

記住 w 兩側要加引號。否則會報錯。

In [51]: w in permission
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-51-7a03fc4c0ccc> in <module>()
----> 1 w in permission

NameError: name 'w' is not defined

In [56]: option=['a','b','c']

In [57]: input("a/b/c: ") in option
a/b/c: b
Out[57]: True

In [58]: input("a/b/c: ") in option
a/b/c: d
Out[58]: False

In [59]: subject = '$$$ Get rich now!!! $$$' 

In [60]: "$$" in subject
Out[60]: True

如上所示,可使用運算子 in 來檢查指定的字串是否為另一個字串的子串。

長度、最小值和最大值

內建函式len、min和max很有用,其中函式len返回序列包含的元素個數,而min和max分別返回序列中最小和最大的元素。

In [67]: numbers =[100, 77, 12]

In [68]: len(numbers)
Out[68]: 3

In [69]: max(numbers)
Out[69]: 100

In [70]: min(numbers)
Out[70]: 12

In [71]: subject="Hello!"

In [72]: len(subject)
Out[72]: 6

In [64]: my_string = "abcdefg"

In [65]: max(my_string)
Out[65]: 'g'

In [66]: min(my_string)
Out[66]: 'a'

【End】

參考資料

《Python基礎教程(第三版)》,人民郵電出版社

相關文章