简明Python教程学习笔记_4_数据结构
在Python中有三種內(nèi)建的數(shù)據(jù)結(jié)構(gòu)——列表、元組和字典。
列表
list是處理一組有序項(xiàng)目的數(shù)據(jù)結(jié)構(gòu),即你可以在一個列表中存儲一個 序列 的項(xiàng)目。假想你有一個購物列表,上面記載著你要買的東西,你就容易理解列表了。只不過在你的購物表上,可能每樣?xùn)|西都獨(dú)自占有一行,而在Python中,你在每個項(xiàng)目之間用逗號分割。
列表中的項(xiàng)目應(yīng)該包括在方括號中,這樣Python就知道你是在指明一個列表。一旦你創(chuàng)建了一個列表,你可以添加、刪除或是搜索列表中的項(xiàng)目。由于你可以增加或刪除項(xiàng)目,我們說列表是可變的 數(shù)據(jù)類型,即這種類型是可以被改變的。
>>>mylist=[1,2,3,a,b,c] >>>type(mylist) >>><type 'list'> >>>dir(list) >>>dir(mylist) >>>help(list)對象與類的快速入門
盡管我一直推遲討論對象和類,但是現(xiàn)在對它們做一點(diǎn)解釋可以使你更好的理解列表。我們會在相應(yīng)的章節(jié)詳細(xì)探索這個主題。
列表是使用對象和類的一個例子。當(dāng)你使用變量i并給它賦值的時候,比如賦整數(shù)5,你可以認(rèn)為你創(chuàng)建了一個類(類型)int的對象(實(shí)例)i。事實(shí)上,你可以看一下help(int)以更好地理解這一點(diǎn)。
類也有方法,即僅僅為類而定義地函數(shù)。僅僅在你有一個該類的對象的時候,你才可以使用這些功能。例如,Python為list類提供了append方法,這個方法讓你在列表尾添加一個項(xiàng)目。例如mylist.append('an item')列表mylist中增加那個字符串。注意,使用點(diǎn)號來使用對象的方法。
一個類也有域,它是僅僅為類而定義的變量。僅僅在你有一個該類的對象的時候,你才可以使用這些變量/名稱。類也通過點(diǎn)號使用,例如mylist.field。
使用列表#!/usr/bin/python # Filename: using_list.py# This is my shopping list shoplist = ['apple', 'mango','carrot','banana']print 'I have', len(shoplist),'items to purchase.' print 'These items are:',# Notice the comma at end of the line for item in shoplist:print item, print '\nI also have to buy rice.' shoplist.append('rice') print 'My shopping list is now', shoplistprint 'I will sort my list now' shoplist.sort() print 'Sorted shopping list is', shoplistprint '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中,我們只存儲購買的東西的名字字符串,但是記住,你可以在列表中添加任何種類的對象 包括數(shù)甚至其他列表。
我們也使用了for..in循環(huán)在列表中各項(xiàng)目間遞歸。從現(xiàn)在開始,你一定已經(jīng)意識到列表也是一個序列。序列的特性會在后面的章節(jié)中討論。
注意,我們在print語句的結(jié)尾使用了一個 逗號 來消除每個print語句自動打印的換行符。這樣做有點(diǎn)難看,不過確實(shí)簡單有效。
接下來,我們使用append方法在列表中添加了一個項(xiàng)目,就如前面已經(jīng)討論過的一樣。然后我們通過打印列表的內(nèi)容來檢驗(yàn)這個項(xiàng)目是否確實(shí)被添加進(jìn)列表了。打印列表只需簡單地把列表傳遞給print語句,我們可以得到一個整潔的輸出。
再接下來,我們使用列表的sort方法來對列表排序。需要理解的是,這個方法影響列表本身,而不是返回一個修改后的列表——這與字符串工作的方法不同。這就是我們所說的列表是可變的 而字符串是不可變的 。
最后,但我們完成了在市場購買一樣?xùn)|西的時候,我們想要把它從列表中刪除。我們使用del語句來完成這個工作。這里,我們指出我們想要刪除列表中的哪個項(xiàng)目,而del語句為我們從列表中刪除它。我們指明我們想要刪除列表中的第一個元素,因此我們使用del shoplist[0](記住,Python從0開始計(jì)數(shù))。
如果你想要知道列表對象定義的所有方法,可以通過help(list)獲得完整的知識。
列表綜合
通過列表綜合,可以從一個已有的列表導(dǎo)出一個新的列表。例如,你有一個數(shù)的列表,而你想要得到一個對應(yīng)的列表,使其中所有大于2的數(shù)都是原來的2倍。對于這種應(yīng)用,列表綜合是最理想的方法。
dfadsf
使用列表綜合
#!/usr/bin/python # Filename: list_comprehension.pylistone = [2, 3,4] listtwo = [2*i for i in listone if i>2] print listtwo 輸出 $ python list_comprehension.py [6, 8]它如何工作
這里我們?yōu)闈M足條件(if i > 2)的數(shù)指定了一個操作(2*i),從而導(dǎo)出一個新的列表。注意原來的列表并沒有發(fā)生變化。在很多時候,我們都是使用循環(huán)來處理列表中的每一個元素,而使用列表綜合可以用一種更加精確、簡潔、清楚的方法完成相同的工作。
元組
元組和列表十分類似,只不過元組和字符串一樣是? 不可變的?即你不能修改元組。元組通過圓括號中用逗號分割的項(xiàng)目定義。元組通常用在使語句或用戶定義的函數(shù)能夠安全地采用一組值的時候,即被使用的元組的值不會改變。使用元組
#!/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函數(shù)可以用來獲取元組的長度。這也表明元組也是一個序列。
由于老動物園關(guān)閉了,我們把動物轉(zhuǎn)移到新動物園。因此,new_zoo元組包含了一些已經(jīng)在那里的動物和從老動物園帶過來的動物。回到話題,注意元組之內(nèi)的元組不會失去它的身份。
我們可以通過一對方括號來指明某個項(xiàng)目的位置從而來訪問元組中的項(xiàng)目,就像我們對列表的用法一樣。這被稱作 索引 運(yùn)算符。我們使用new_zoo[2]來訪問new_zoo中的第三個項(xiàng)目。我們使用new_zoo[2][2]來訪問new_zoo元組的第三個項(xiàng)目的第三個項(xiàng)目。
含有0個或1個項(xiàng)目的元組。
一個空的元組由一對空的圓括號組成,如myempty = ()。然而,含有單個元素的元組就不那么簡單了。你必須在第一個(唯一一個)項(xiàng)目后跟一個逗號,這樣Python才能區(qū)分元組和表達(dá)式中一個帶圓括號的對象。即如果你想要的是一個包含項(xiàng)目2的元組的時候,你應(yīng)該指明singleton = (2 , )。
給Perl程序員的注釋
列表之中的列表不會失去它的身份,即列表不會像Perl中那樣被打散。同樣元組中的元組,或列表中的元組,或元組中的列表等等都是如此。只要是Python,它們就只是使用另一個對象存儲的對象。
元組與打印語句
元組最通常的用法是用在打印語句中,下面是一個例子:
#!/usr/bin/python # Filename: print_tuple.pyage = 22 name = '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?dictName={'name':'xiaoming','name1':'xiaofang','name2':'huangdi'} print 'dictName[name] ',dictName['name'] print '\n' print 'dictName[name] %s'%dictName['name'] print '\n' print 'dictName[name1] ,dictName[name2] ',dictName['name1'],dictName['name2'] print '\n' print 'dictName[name1] %s ,dictName[name2] %s'%(dictName['name1'],dictName['name2'])它如何工作
print語句可以使用跟著%符號的項(xiàng)目元組的字符串。這些字符串具備定制的功能。定制讓輸出滿足某種特定的格式。定制可以是%s表示字符串或%d表示整數(shù)。元組必須按照相同的順序來對應(yīng)這些定制。
觀察我們使用的第一個元組,我們首先使用%s,這對應(yīng)變量name,它是元組中的第一個項(xiàng)目。而第二個定制是%d,它對應(yīng)元組的第二個項(xiàng)目age。
Python在這里所做的是把元組中的每個項(xiàng)目轉(zhuǎn)換成字符串并且用字符串的值替換定制的位置。因此%s被替換為變量name的值,依此類推。
print的這個用法使得編寫輸出變得極其簡單,它避免了許多字符串操作。它也避免了我們一直以來使用的逗號。
在大多數(shù)時候,你可以只使用%s定制,而讓Python來提你處理剩余的事情。這種方法對數(shù)同樣奏效。然而,你可能希望使用正確的定制,從而可以避免多一層的檢驗(yàn)程序是否正確。
在第二個print語句中,我們使用了一個定制,后面跟著%符號后的單個項(xiàng)目——沒有圓括號。這只在字符串中只有一個定制的時候有效。
交換變量值
一般的交換兩個變量的值是用過一個臨時變量、或者 異或、或者相加、或者相乘。但是 Python中有一種賦值機(jī)制即多元賦值,采用這種方式賦值時,等號兩邊的對象都是元組并且元組的小括號是可選的。通常形式為
x, y, z = 1, 2, 'a string'等同于 (x, y, z) = (1, 2, 'a string') 。這種賦值類型最經(jīng)常用到的環(huán)境是變量交換,形如: ?x, y = y, x
這種交換方式無需中間變量即可交換兩個變量的值。那么具體實(shí)現(xiàn)機(jī)制是怎樣的呢?
運(yùn)行時,首先構(gòu)造一個元組(y, x),然后構(gòu)造另一個元組(x, y),接著用元組(y, x)賦值給(x, y),元組賦值過程從左到右,依次進(jìn)行。假如x=1,y=2,先令x=y,此時x=2,然后令y=x,y應(yīng)該等于2?那么就不能實(shí)現(xiàn)變量交換了?對于這個問題,應(yīng)該從元組的特性說起。
x, y, z = 1, 2, 'a string'
tuple = (x, y, z)
變量名x, y, z都是引用,內(nèi)存開辟除了三個空間分別存儲1, 2, 'a string',三個變量分別指向這三塊地址。由這三個變量構(gòu)造的元組tuple,它有三個元素,這三個元素并不是x,y,z這三個變量,而是這三個變量所指向的地址空間里的內(nèi)容。如果此時再另x=4,此時在地址空間會另開辟出一塊空間存儲4,x進(jìn)而指向這塊空間,而元組內(nèi)的三個值仍保持不變。
所以對于 x, y = y, x 來說,首先由y,x所構(gòu)成的元組(y,x)其實(shí)應(yīng)該表示為(2,1),那么再從左到右賦值,就可以交換變量的值了。
在函數(shù)中接收元組和列表
使函數(shù)接收元組或字典形式的參數(shù)的時候,可以分別使用 ?*?和 ?**?前綴。這種方法在函數(shù)需要獲取可變數(shù)量的參數(shù)的時候特別有用。
>>> def powersum(power, *args): ... '''Return the sum of each argument raised to specified power.''' ... total = 0 ... for i in args: ... total += pow(i, power) ... return total ... >>> powersum(2, 3, 4) 25>>> powersum(2, 10) 100由于在args變量前有*前綴,所有多余的函數(shù)參數(shù)都會作為一個元組存儲在args中。如果使用的是**前綴,多余的參數(shù)則會被認(rèn)為是一個字典的鍵/值對。
字典
字典類似于你通過聯(lián)系人名字查找地址和聯(lián)系人詳細(xì)情況的地址簿,即,我們把鍵(名字)和值(詳細(xì)情況)聯(lián)系在一起。注意,鍵必須是唯一的,就像如果有兩個人恰巧同名的話,你無法找到正確的信息。
注意,你只能使用不可變的對象(比如字符串)來作為字典的鍵,但是你可以使用不可變或可變的對象作為字典的值。基本說來就是,你應(yīng)該只使用簡單的對象作為鍵。
鍵值對在字典中以這樣的方式標(biāo)記:d = {key1 : value1, key2 : value2 }。注意它們的鍵/值對用冒號分割,而各個對用逗號分割,所有這些都包括在花括號中。
記住字典中的鍵/值對是沒有順序的。如果你想要一個特定的順序,那么你應(yīng)該在使用前自己對它們排序。
字典是dict類的實(shí)例/對象。
#!/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 pair ab['Guido'] = 'guido@python.org'# Deleting a key/value pair del 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' inab:# OR ab.has_key('Guido')print "\nGuido's address is %s" % ab['Guido']結(jié)果 $ python using_dict.py Swaroop's address is swaroopch@byteofpython.infoThere are 4 contacts in the address-bookContact Swaroop at swaroopch@byteofpython.info Contact Matsumoto at matz@ruby-lang.org Contact Larry at larry@wall.org Contact Guido at guido@python.orgGuido's address is guido@python.org它如何工作
我們使用已經(jīng)介紹過的標(biāo)記創(chuàng)建了字典ab。然后我們使用在列表和元組章節(jié)中已經(jīng)討論過的索引操作符來指定鍵,從而使用鍵/值對。我們可以看到字典的語法同樣十分簡單。
我們可以使用索引操作符來尋址一個鍵并為它賦值,這樣就增加了一個新的鍵/值對,就像在上面的例子中我們對Guido所做的一樣。
我們可以使用我們的老朋友——del語句來刪除鍵/值對。我們只需要指明字典和用索引操作符指明要刪除的鍵,然后把它們傳遞給del語句就可以了。執(zhí)行這個操作的時候,我們無需知道那個鍵所對應(yīng)的值。
接下來,我們使用字典的items方法,來使用字典中的每個鍵/值對。這會返回一個元組的列表,其中每個元組都包含一對項(xiàng)目——鍵與對應(yīng)的值。我們抓取這個對,然后分別賦給for..in循環(huán)中的變量name和address然后在for-塊中打印這些值。
我們可以使用in操作符來檢驗(yàn)一個鍵/值對是否存在,或者使用dict類的has_key方法。你可以使用help(dict)來查看dict類的完整方法列表。
關(guān)鍵字參數(shù)與字典。如果換一個角度看待你在函數(shù)中使用的關(guān)鍵字參數(shù)的話,你已經(jīng)使用了字典了!只需想一下——你在函數(shù)定義的參數(shù)列表中使用的鍵/值對。當(dāng)你在函數(shù)中使用變量的時候,它只不過是使用一個字典的鍵(這在編譯器設(shè)計(jì)的術(shù)語中被稱作符號表?)。
序列
列表、元組和字符串都是序列,但是序列是什么,它們?yōu)槭裁慈绱颂貏e呢?序列的兩個主要特點(diǎn)是索引操作符和切片操作符。索引操作符讓我們可以從序列中抓取一個特定項(xiàng)目。切片操作符讓我們能夠獲取序列的一個切片,即一部分序列。
切片操作:[開始位置:結(jié)束位置:步長]
tempList=[0,1,2,3,4,5] print tempList[::4]#結(jié)果 [0, 4] 從 開始位置 到 結(jié)束位置 且步長為4的位置的值 組成一個新的List ,并打印temp = [x for x in range(11)] print tem0[::2] print temp[::] print temp[1:-1]
它如何工作
首先,我們來學(xué)習(xí)如何使用索引來取得序列中的單個項(xiàng)目。這也被稱作是下標(biāo)操作。每當(dāng)你用方括號中的一個數(shù)來指定一個序列的時候,Python會為你抓取序列中對應(yīng)位置的項(xiàng)目。記住,Python從0開始計(jì)數(shù)。因此,shoplist[0]抓取第一個項(xiàng)目,shoplist[3]抓取shoplist序列中的第四個元素。
索引同樣可以是負(fù)數(shù),在那樣的情況下,位置是從序列尾開始計(jì)算的。因此,shoplist[-1]表示序列的最后一個元素而shoplist[-2]抓取序列的倒數(shù)第二個項(xiàng)目。
切片操作符是序列名后跟一個方括號,方括號中有一對可選的數(shù)字,并用冒號分割。注意這與你使用的索引操作符十分相似。記住數(shù)是可選的,而冒號是必須的。
切片操作符中的第一個數(shù)(冒號之前)表示切片開始的位置,第二個數(shù)(冒號之后)表示切片到哪里結(jié)束。如果不指定第一個數(shù),Python就從序列首開始。如果沒有指定第二個數(shù),則Python會停止在序列尾。注意,返回的序列從開始位置開始?,剛好在結(jié)束?位置之前結(jié)束。即開始位置是包含在序列切片中的,而結(jié)束位置被排斥在切片外。
這樣,shoplist[1:3]返回從位置1開始,包括位置2,但是停止在位置3的一個序列切片,因此返回一個含有兩個項(xiàng)目的切片。類似地,shoplist[:]返回整個序列的拷貝。
你可以用負(fù)數(shù)做切片。負(fù)數(shù)用在從序列尾開始計(jì)算的位置。例如,shoplist[:-1]會返回除了最后一個項(xiàng)目外包含所有項(xiàng)目的序列切片。
使用Python解釋器交互地嘗試不同切片指定組合,即在提示符下你能夠馬上看到結(jié)果。序列的神奇之處在于你可以用相同的方法訪問元組、列表和字符串。
參考
當(dāng)你創(chuàng)建一個對象并給它賦一個變量的時候,這個變量僅僅?參考?那個對象,而不是表示這個對象本身!也就是說,變量名指向你計(jì)算機(jī)中存儲那個對象的內(nèi)存。這被稱作名稱到對象的綁定。
一般說來,你不需要擔(dān)心這個,只是在參考上有些細(xì)微的效果需要你注意。這會通過下面這個例子加以說明。
對象與參考
#!/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 slice del 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']它如何工作
大多數(shù)解釋已經(jīng)在程序的注釋中了。你需要記住的只是如果你想要復(fù)制一個列表或者類似的序列或者其他復(fù)雜的對象(不是如整數(shù)那樣的簡單?對象?),那么你必須使用切片操作符來取得拷貝。如果你只是想要使用另一個變量名,兩個名稱都參考?同一個對象,那么如果你不小心的話,可能會引來各種麻煩。
給Perl程序員的注釋
記住列表的賦值語句不創(chuàng)建拷貝。你得使用切片操作符來建立序列的拷貝。??
更多字符串的內(nèi)容
我們已經(jīng)在前面詳細(xì)討論了字符串。我們還需要知道什么呢?那么,你是否知道字符串也是對象,同樣具有方法。這些方法可以完成包括檢驗(yàn)一部分字符串和去除空格在內(nèi)的各種工作。
你在程序中使用的字符串都是str類的對象。這個類的一些有用的方法會在下面這個例子中說明。如果要了解這些方法的完整列表,請參見help(str)。
字符串的方法
#!/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操作符用來檢驗(yàn)一個給定字符串是否為另一個字符串的一部分。
find方法用來找出給定字符串在另一個字符串中的位置,或者返回-1以表示找不到子字符串。str類也有以一個作為分隔符的字符串join序列的項(xiàng)目的整潔的方法,它返回一個生成的大字符串。
總結(jié)
以上是生活随笔為你收集整理的简明Python教程学习笔记_4_数据结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小甲鱼 OllyDbg 教程系列 (二)
- 下一篇: Python 包管理工具 pip 安装