list是處理一組有序項目的資料結構,即你可以在一個列表中儲存一個 序列 的項目。假想你有一個購物列表,上面記載著你要買的東西,你就容易理解列表了。只不過在你的購物表上,可能每樣東西都獨自佔有一行,而在Python中,你在每個項目之間用逗號分割。
列表中的項目應該包括在方括弧中,這樣Python就知道你是在指明一個列表。一旦你建立了一個列表,你可以添加、刪除或是搜尋列表中的項目。由於你可以增加或刪除項目,我們說列表是 可變的 資料類型,即這種類型是可以被改變的。
列表是使用對象和類的一個例子。當你使用變數i並給它賦值的時候,比如賦整數5,你可以認為你建立了一個類(類型)int的對象(執行個體)i。事實上,你可以看一下help(int)以更好地理解這一點。
類也有方法,即僅僅為類而定義地函數。僅僅在你有一個該類的對象的時候,你才可以使用這些功能。例如,Python為list類提供了append方法,這個方法讓你在列表尾添加一個項目。例如mylist.append('an item')列表mylist中增加那個字串。注意,使用點號來使用對象的方法。
一個類也有域,它是僅僅為類而定義的變數。僅僅在你有一個該類的對象的時候,你才可以使用這些變數/名稱。類也通過點號使用,例如mylist.field。
使用列表
例1 使用列表
#!/usr/bin/python# Filename: using_list.py# This is my shopping listshoplist = ['apple', 'mango', 'carrot', 'banana']print('I have', len(shoplist),'items to purchase.')print('These items are:') # Notice the comma at end of the linefor item in shoplist: print(item)print('\nI also have to buy rice.')shoplist.append('rice')print('My shopping list is now', shoplist)print('I will sort my list now')shoplist.sort()print('Sorted shopping list is', shoplist)print('The first item I will buy is', shoplist[0])olditem = shoplist[0]del shoplist[0]print('I bought the', olditem)print('My shopping list is now', shoplist )
輸出
$ python using_list.py
I have 4 items to purchase.
These items are: apple mango carrot banana
I also have to buy rice.
My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice']
I will sort my list now
Sorted shopping list is ['apple', 'banana', 'carrot', 'mango', 'rice']
The first item I will buy is apple
I bought the apple
My shopping list is now ['banana', 'carrot', 'mango', 'rice']
變數shoplist是某人的購物列表。在shoplist中,我們只儲存購買的東西的名字字串,但是記住,可以在列表中添加 任何種類的對象 包括數甚至其他列表。
我們也使用了for..in迴圈在列表中各項目間遞迴。從現在開始,你一定已經意識到列表也是一個序列。序列的特性會在後面的章節中討論。
接下來,使用append方法在列表中添加了一個項目,就如前面已經討論過的一樣。然後我們通過列印列表的內容來檢驗這個項目是否確實被添加進列表了。列印列表只需簡單地把列表傳遞給print語句,我們可以得到一個整潔的輸出。
再接下來,我們使用列表的sort方法來對列表排序。需要理解的是,這個方法影響列表本身,而不是返回一個修改後的列表——這與字串工作的方法不同。這就是我們所說的列表是 可變的 而字串是 不可變的 。
最後,但我們完成了在市場購買一樣東西的時候,我們想要把它從列表中刪除。我們使用del語句來完成這個工作。這裡,我們指出我們想要刪除列表中的哪個項目,而del語句為我們從列表中刪除它。我們指明我們想要刪除列表中的第一個元素,因此我們使用del shoplist[0](從0開始計數)。
如果你想要知道列表對象定義的所有方法,可以通過help(list)獲得完整的知識。
元組和列表十分類似,只不過元組和字串一樣是 不可變的 即你不能修改元組。元組通過圓括弧中用逗號分割的項目定義。元組通常用在使語句或使用者定義的函數能夠安全地採用一組值的時候,即被使用的元組的值不會改變。
使用元組
例2 使用元組
#!/usr/bin/python# Filename: using_tuple.pyzoo = ('wolf', 'elephant', 'penguin')print('Number of animals in the zoo is', len(zoo))new_zoo = ('monkey', 'dolphin', zoo)print('Number of animals in the new zoo is', len(new_zoo))print('All animals in new zoo are', new_zoo)print('Animals brought from old zoo are', new_zoo[2])print('Last animal brought from old zoo is', new_zoo[2][2])
輸出
$ python using_tuple.py
Number of animals in the zoo is 3
Number of animals in the new zoo is 3
All animals in new zoo are ('monkey', 'dolphin', ('wolf', 'elephant', 'penguin'))
Animals brought from old zoo are ('wolf', 'elephant', 'penguin')
Last animal brought from old zoo is penguin
它如何工作
變數zoo是一個元組,我們看到len函數可以用來擷取元組的長度。這也表明元組也是一個序列。
由於老動物園關閉了,我們把動物轉移到新動物園。因此,new_zoo元組包含了一些已經在那裡的動物和從老動物園帶過來的動物。回到話題,注意元組之內的元組不會失去它的身份。
我們可以通過一對方括弧來指明某個項目的位置從而來訪問元組中的項目,就像我們對列表的用法一樣。這被稱作 索引 運算子。我們使用new_zoo[2]來訪問new_zoo中的第三個項目。我們使用new_zoo[2][2]來訪問new_zoo元組的第三個項目的第三個項目。
含有0個或1個項目的元組。一個空的元組由一對空的圓括弧組成,如myempty = ()。
然而,含有單個元素的元組就不那麼簡單了。你必須在第一個(唯一一個)項目後跟一個逗號,這樣Python才能區分元組和運算式中一個帶圓括弧的對象。即如果你想要的是一個包含項目2的元組的時候,你應該指明singleton = (2 , )。
元組與列印語句
元組最通常的用法是用在列印語句中,下面是一個例子:
例3 使用元組輸出
#!/usr/bin/python# Filename: print_tuple.pyage = 22name = 'Swaroop'print('%s is %d years old' % (name, age))print('Why is %s playing with that python?' % name)
輸出
$ python print_tuple.py
Swaroop is 22 years old
Why is Swaroop playing with that python?
它如何工作
print語句可以使用跟著%符號的項目元組的字串。這些字串具備定製的功能。定製讓輸出滿足某種特定的格式。定製可以是%s表示字串或%d表示整數。元組必須按照相同的順序來對應這些定製。
觀察我們使用的第一個元組,我們首先使用%s,這對應變數name,它是元組中的第一個項目。而第二個定製是%d,它對應元組的第二個項目age。
Python在這裡所做的是把元組中的每個項目轉換成字串並且用字串的值替換定製的位置。因此%s被替換為變數name的值,依此類推。
print的這個用法使得編寫輸出變得極其簡單,它避免了許多字串操作。它也避免了我們一直以來使用的逗號。
在大多數時候,你可以只使用%s定製,而讓Python來提你處理剩餘的事情。這種方法對數同樣奏效。然而,你可能希望使用正確的定製,從而可以避免多一層的檢驗程式是否正確。
在第二個print語句中,我們使用了一個定製,後面跟著%符號後的單個項目——沒有圓括弧。這隻在字串中只有一個定製的時候有效。
字典類似於你通過連絡人名字尋找地址和連絡人詳細情況的地址簿,即,我們把鍵(名字)和值(詳細情況)聯絡在一起。注意,鍵必須是唯一的,就像如果有兩個人恰巧同名的話,你無法找到正確的資訊。
注意,你只能使用不可變的對象(比如字串)來作為字典的鍵,但是你可以不可變或可變的對象作為字典的值。基本說來就是,你應該只使用簡單的對象作為鍵。
索引值對在字典中以這樣的方式標記:d = {key1 : value1, key2 : value2 }。注意它們的鍵/值對用冒號分割,而各個對用逗號分割,所有這些都包括在花括弧中。
記住字典中的鍵/值對是沒有順序的。如果你想要一個特定的順序,那麼你應該在使用前自己對它們排序。
字典是dict類的執行個體/對象。
使用字典
例4 使用字典
#!/usr/bin/python# Filename: using_dict.py# 'ab' is short for 'a'ddress'b'ookab = { 'Swaroop' : 'swaroopch@byteofpython.info', 'Larry' : 'larry@wall.org', 'Matsumoto' : 'matz@ruby-lang.org', 'Spammer' : 'spammer@hotmail.com' }print("Swaroop's address is %s" % ab['Swaroop'])# Adding a key/value pairab['Guido'] = 'guido@python.org'# Deleting a key/value pairdel ab['Spammer']print('\nThere are %d contacts in the address-book\n' % len(ab))for name, address in ab.items(): print('Contact %s at %s' % (name, address))if 'Guido' in ab: # OR ab.has_key('Guido') print("\nGuido's address is %s" % ab['Guido'])
輸出
$ python using_dict.py
Swaroop's address is swaroopch@byteofpython.info
There are 4 contacts in the address-book
Contact Swaroop at swaroopch@byteofpython.info
Contact Matsumoto at matz@ruby-lang.org
Contact Larry at larry@wall.org
Contact Guido at guido@python.org
Guido's address is guido@python.org
它如何工作
我們使用已經介紹過的標記建立了字典ab。然後我們使用在列表和元組章節中已經討論過的索引操作符來指定鍵,從而使用鍵/值對。我們可以看到字典的文法同樣十分簡單。
我們可以使用索引操作符來定址一個鍵並為它賦值,這樣就增加了一個新的鍵/值對,就像在上面的例子中我們對Guido所做的一樣。
我們可以使用我們的老朋友——del語句來刪除鍵/值對。我們只需要指明字典和用索引操作符指明要刪除的鍵,然後把它們傳遞給del語句就可以了。執行這個操作的時候,我們無需知道那個鍵所對應的值。
接下來,我們使用字典的items方法,來使用字典中的每個鍵/值對。這會返回一個元組的列表,其中每個元組都包含一對項目——鍵與對應的值。我們抓取這個對,然後分別賦給for..in迴圈中的變數name和address然後在for-塊中列印這些值。
我們可以使用in操作符來檢驗一個鍵/值對是否存在,或者使用dict類的has_key方法。你可以使用help(dict)來查看dict類的完整方法列表。
關鍵字參數與字典。如果換一個角度看待你在函數中使用的關鍵字參數的話,你已經使用了字典了!只需想一下——你在函數定義的參數列表中使用的鍵/值對。當你在函數中使用變數的時候,它只不過是使用一個字典的鍵(這在編譯器設計的術語中被稱作 符號表 )。
列表、元組和字串都是序列,但是序列是什麼,它們為什麼如此特別呢?序列的兩個主要特點是索引操作符和切片操作符。索引操作符讓我們可以從序列中抓取一個特定項目。切片操作符讓我們能夠擷取序列的一個切片,即一部分序列。
使用序列
例5 使用序列
#!/usr/bin/python# Filename: seq.pyshoplist = ['apple', 'mango', 'carrot', 'banana']# Indexing or 'Subscription' operationprint('Item 0 is', shoplist[0])print('Item 1 is', shoplist[1])print('Item 2 is', shoplist[2])print('Item 3 is', shoplist[3])print('Item -1 is', shoplist[-1])print('Item -2 is', shoplist[-2])# Slicing on a listprint('Item 1 to 3 is', shoplist[1:3])print('Item 2 to end is', shoplist[2:])print('Item 1 to -1 is', shoplist[1:-1])print('Item start to end is', shoplist[:])# Slicing on a stringname = 'swaroop'print('characters 1 to 3 is', name[1:3])print('characters 2 to end is', name[2:])print('characters 1 to -1 is', name[1:-1])print('characters start to end is', name[:])
輸出
$ python seq.py
Item 0 is apple
Item 1 is mango
Item 2 is carrot
Item 3 is banana
Item -1 is banana
Item -2 is carrot
Item 1 to 3 is ['mango', 'carrot']
Item 2 to end is ['carrot', 'banana']
Item 1 to -1 is ['mango', 'carrot']
Item start to end is ['apple', 'mango', 'carrot', 'banana']
characters 1 to 3 is wa
characters 2 to end is aroop
characters 1 to -1 is waroo
characters start to end is swaroop
它如何工作
首先,我們來學習如何使用索引來取得序列中的單個項目。這也被稱作是下標操作。每當你用方括弧中的一個數來指定一個序列的時候,Python會為你抓取序列中對應位置的項目。記住,Python從0開始計數。因此,shoplist[0]抓取第一個項目,shoplist[3]抓取shoplist序列中的第四個元素。
索引同樣可以是負數,在那樣的情況下,位置是從序列尾開始計算的。因此,shoplist[-1]表示序列的最後一個元素而shoplist[-2]抓取序列的倒數第二個項目。
切片操作符是序列名後跟一個方括弧,方括弧中有一對可選的數字,並用冒號分割。注意這與你使用的索引操作符十分相似。記住數是可選的,而冒號是必須的。
切片操作符中的第一個數(冒號之前)表示切片開始的位置,第二個數(冒號之後)表示切片到哪裡結束。如果不指定第一個數,Python就從序列首開始。如果沒有指定第二個數,則Python會停止在序列尾。注意,返回的序列從開始位置 開始 ,剛好在 結束 位置之前結束。即開始位置是包含在序列切片中的,而結束位置被排斥在切片外。
這樣,shoplist[1:3]返回從位置1開始,包括位置2,但是停止在位置3的一個序列切片,因此返回一個含有兩個項目的切片。類似地,shoplist[:]返回整個序列的拷貝。
你可以用負數做切片。負數用在從序列尾開始計算的位置。例如,shoplist[:-1]會返回除了最後一個項目外包含所有項目的序列切片。
使用Python解譯器互動地嘗試不同切片指定組合,即在提示符下你能夠馬上看到結果。序列的神奇之處在於你可以用相同的方法訪問元組、列表和字串。
當你建立一個對象並給它賦一個變數的時候,這個變數僅僅 參考 那個對象,而不是表示這個對象本身!也就是說,變數名指向你電腦中儲存那個對象的記憶體。這被稱作名稱到對象的綁定。
一般說來,你不需要擔心這個,只是在參考上有些細微的效果需要你注意。這會通過下面這個例子加以說明。
對象與參考
例6 對象與參考
#!/usr/bin/python# Filename: reference.pyprint('Simple Assignment')shoplist = ['apple', 'mango', 'carrot', 'banana']mylist = shoplist # mylist is just another name pointing to the same object!del shoplist[0]print('shoplist is', shoplist)print('mylist is', mylist)# notice that both shoplist and mylist both print the same list without# the 'apple' confirming that they point to the same objectprint('Copy by making a full slice')mylist = shoplist[:] # make a copy by doing a full slicedel mylist[0] # remove first itemprint('shoplist is', shoplist)print('mylist is', mylist)# notice that now the two lists are different
輸出
$ python reference.py
Simple Assignment
shoplist is ['mango', 'carrot', 'banana']
mylist is ['mango', 'carrot', 'banana']
Copy by making a full slice
shoplist is ['mango', 'carrot', 'banana']
mylist is ['carrot', 'banana']
它如何工作
大多數解釋已經在程式的注釋中了。你需要記住的只是如果你想要複製一個列表或者類似的序列或者其他複雜的對象(不是如整數那樣的簡單 對象 ),那麼你必須使用切片操作符來取得拷貝。如果你只是想要使用另一個變數名,兩個名稱都 參考 同一個對象,那麼如果你不小心的話,可能會引來各種麻煩。
字串
我們已經在前面詳細討論了字串。我們還需要知道什麼呢?那麼,你是否知道字串也是對象,同樣具有方法。這些方法可以完成包括檢驗一部分字串和去除空格在內的各種工作。
你在程式中使用的字串都是str類的對象。這個類的一些有用的方法會在下面這個例子中說明。如果要瞭解這些方法的完整列表,請參見help(str)。
字串的方法
例7 字串的方法
#!/usr/bin/python# Filename: str_methods.pyname = 'Swaroop' # This is a string objectif name.startswith('Swa'): print('Yes, the string starts with "Swa"')if 'a' in name: print('Yes, it contains the string "a"')if name.find('war') != -1: print('Yes, it contains the string "war"')delimiter = '_*_'mylist = ['Brazil', 'Russia', 'India', 'China']print(delimiter.join(mylist))
輸出
$ python str_methods.py
Yes, the string starts with "Swa"
Yes, it contains the string "a"
Yes, it contains the string "war"
Brazil_*_Russia_*_India_*_China
它如何工作
這裡,我們看到使用了許多字串方法。startwith方法是用來測試字串是否以給定字串開始。in操作符用來檢驗一個給定字串是否為另一個字串的一部分。
find方法用來找出給定字串在另一個字串中的位置,或者返回-1以表示找不到子字串。str類也有以一個作為分隔字元的字串join序列的項目的整潔的方法,它返回一個產生的大字串。