鍍金池/ 教程/ Python/ 數(shù)據(jù)結(jié)構(gòu)
備份腳本——版本四
使用 <strong>init</strong> 方法
控制流
異常
表 15.1 一些特殊的方法
如何創(chuàng)建你自己的模塊
使用字典
前言
使用默認參數(shù)值
表 5.1 運算符與它們的用法
解決問題——編寫一個 Python 腳本
使用 for 語句
使用 continue 語句
使用元組輸出
對象與參考
使用函數(shù)形參
使用默認參數(shù)值
使用 if 語句
如何引發(fā)異常
使用源文件
使用對象的方法
使用表達式
定義函數(shù)
使用局部變量
使用列表綜合
使用 sys.argv
使用 lambda 形式
使用 global 語句
備份腳本——版本二
使用列表
使用 while 語句
備份腳本——版本一
使用元組
輸入/輸出
使用類與對象的變量
使用 sys 模塊
表 5.2 運算符優(yōu)先級
處理異常
使用 break 語句
函數(shù)
基本概念
運算符與表達式
介紹
使用文件
使用序列
接下來學習什么?
使用帶提示符的 Python 解釋器
使用 DocStrings
使用字面意義上的語句
最初的步驟
數(shù)據(jù)結(jié)構(gòu)
儲存與取儲存
使用 dir 函數(shù)
模塊
Python 標準庫
備份腳本——版本三(不工作?。?/span>
創(chuàng)建一個類
安裝 Python
面向?qū)ο蟮木幊?/span>
使用模塊的<strong>name</strong>
使用變量和字面意義上的常量
使用繼承

數(shù)據(jù)結(jié)構(gòu)

簡介

數(shù)據(jù)結(jié)構(gòu)基本上就是——它們是可以處理一些 數(shù)據(jù)結(jié)構(gòu) 。或者說,它們是用來存儲一組相關數(shù)據(jù)的。

在 Python 中有三種內(nèi)建的數(shù)據(jù)結(jié)構(gòu)——列表、元組和字典。我們將會學習如何使用它們,以及它們?nèi)绾问咕幊套兊煤唵巍?/p>

列表

list 是處理一組有序項目的數(shù)據(jù)結(jié)構(gòu),即你可以在一個列表中存儲一個 序列 的項目。假想你有一個購物列表,上面記載著你要買的東西,你就容易理解列表了。只不過在你的購物表上,可能每樣東西都獨自占有一行,而在 Python 中,你在每個項目之間用逗號分割。

列表中的項目應該包括在方括號中,這樣 Python 就知道你是在指明一個列表。一旦你創(chuàng)建了一個列表,你可以添加、刪除或是搜索列表中的項目。由于你可以增加或刪除項目,我們說列表是 可變的 數(shù)據(jù)類型,即這種類型是可以被改變的。

對象與類的快速入門

盡管我一直推遲討論對象和類,但是現(xiàn)在對它們做一點解釋可以使你更好的理解列表。我們會在相應的章節(jié)詳細探索這個主題。

列表是使用對象和類的一個例子。當你使用變量i并給它賦值的時候,比如賦整數(shù) 5,你可以認為你創(chuàng)建了一個(類型)int 的對象(實例)i。事實上,你可以看一下 help(int)以更好地理解這一點。

類也有方法,即僅僅為類而定義地函數(shù)。僅僅在你有一個該類的對象的時候,你才可以使用這些功能。例如,Python 為 list 類提供了 append 方法,這個方法讓你在列表尾添加一個項目。例如 mylist.append('an item')列表 mylist 中增加那個字符串。注意,使用點號來使用對象的方法。

一個類也有,它是僅僅為類而定義的變量。僅僅在你有一個該類的對象的時候,你才可以使用這些變量/名稱。類也通過點號使用,例如 mylist.field。

使用列表

例 9.1 使用列表


    #!/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', 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

(源文件:code/using_list.py

輸出


    $ 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àn)在開始,你一定已經(jīng)意識到列表也是一個序列。序列的特性會在后面的章節(jié)中討論。

注意,我們在 print 語句的結(jié)尾使用了一個 逗號 來消除每個 print 語句自動打印的換行符。這樣做有點難看,不過確實簡單有效。

接下來,我們使用 append 方法在列表中添加了一個項目,就如前面已經(jīng)討論過的一樣。然后我們通過打印列表的內(nèi)容來檢驗這個項目是否確實被添加進列表了。打印列表只需簡單地把列表傳遞給 print 語句,我們可以得到一個整潔的輸出。

再接下來,我們使用列表的 sort 方法來對列表排序。需要理解的是,這個方法影響列表本身,而不是返回一個修改后的列表——這與字符串工作的方法不同。這就是我們所說的列表是 可變的 而字符串是 不可變的 。

最后,但我們完成了在市場購買一樣東西的時候,我們想要把它從列表中刪除。我們使用 del 語句來完成這個工作。這里,我們指出我們想要刪除列表中的哪個項目,而 del 語句為我們從列表中刪除它。我們指明我們想要刪除列表中的第一個元素,因此我們使用 del shoplist[0](記住,Python 從 0 開始計數(shù))。

如果你想要知道列表對象定義的所有方法,可以通過 help(list)獲得完整的知識。

元組

元組和列表十分類似,只不過元組和字符串一樣是 不可變的 即你不能修改元組。元組通過圓括號中用逗號分割的項目定義。元組通常用在使語句或用戶定義的函數(shù)能夠安全地采用一組值的時候,即被使用的元組的值不會改變。

使用元組

例 9.2 使用元組


    #!/usr/bin/python
    # Filename: using_tuple.py

    zoo = ('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]

(源文件:code/using_tuple.py

輸出


    $ 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ù)可以用來獲取元組的長度。這也表明元組也是一個序列

由于老動物園關閉了,我們把動物轉(zhuǎn)移到新動物園。因此,new_zoo 元組包含了一些已經(jīng)在那里的動物和從老動物園帶過來的動物?;氐皆掝},注意元組之內(nèi)的元組不會失去它的身份。

我們可以通過一對方括號來指明某個項目的位置從而來訪問元組中的項目,就像我們對列表的用法一樣。這被稱作 索引 運算符。我們使用 new_zoo[2]來訪問 new_zoo 中的第三個項目。我們使用 new_zoo[2][2]來訪問 new_zoo 元組的第三個項目的第三個項目。

含有 0 個或 1 個項目的元組。一個空的元組由一對空的圓括號組成,如 myempty = ()。然而,含有單個元素的元組就不那么簡單了。你必須在第一個(唯一一個)項目后跟一個逗號,這樣 Python 才能區(qū)分元組和表達式中一個帶圓括號的對象。即如果你想要的是一個包含項目 2 的元組的時候,你應該指明 singleton = (2 , )。

給 Perl 程序員的注釋 列表之中的列表不會失去它的身份,即列表不會像 Perl 中那樣被打散。同樣元組中的元組,或列表中的元組,或元組中的列表等等都是如此。只要是 Python,它們就只是使用另一個對象存儲的對象。

元組與打印語句

元組最通常的用法是用在打印語句中,下面是一個例子:

例 9.3 使用元組輸出


    #!/usr/bin/python
    # Filename: print_tuple.py

    age = 22
    name = 'Swaroop'

    print '%s is %d years old' % (name, age)
    print 'Why is %s playing with that python?' % name

(源文件:code/print_tuple.py)

輸出


    $ python print_tuple.py
    Swaroop is 22 years old
    Why is Swaroop playing with that python?

它如何工作

print 語句可以使用跟著%符號的項目元組的字符串。這些字符串具備定制的功能。定制讓輸出滿足某種特定的格式。定制可以是%s 表示字符串或%d 表示整數(shù)。元組必須按照相同的順序來對應這些定制。

觀察我們使用的第一個元組,我們首先使用%s,這對應變量 name,它是元組中的第一個項目。而第二個定制是%d,它對應元組的第二個項目 age。

Python 在這里所做的是把元組中的每個項目轉(zhuǎn)換成字符串并且用字符串的值替換定制的位置。因此%s 被替換為變量 name 的值,依此類推。

print 的這個用法使得編寫輸出變得極其簡單,它避免了許多字符串操作。它也避免了我們一直以來使用的逗號。

在大多數(shù)時候,你可以只使用%s 定制,而讓 Python 來提你處理剩余的事情。這種方法對數(shù)同樣奏效。然而,你可能希望使用正確的定制,從而可以避免多一層的檢驗程序是否正確。

在第二個 print 語句中,我們使用了一個定制,后面跟著%符號后的單個項目——沒有圓括號。這只在字符串中只有一個定制的時候有效。

字典

字典類似于你通過聯(lián)系人名字查找地址和聯(lián)系人詳細情況的地址簿,即,我們把(名字)和(詳細情況)聯(lián)系在一起。注意,鍵必須是唯一的,就像如果有兩個人恰巧同名的話,你無法找到正確的信息。

注意,你只能使用不可變的對象(比如字符串)來作為字典的鍵,但是你可以不可變或可變的對象作為字典的值?;菊f來就是,你應該只使用簡單的對象作為鍵。

鍵值對在字典中以這樣的方式標記:d = {key1 : value1, key2 : value2 }。注意它們的鍵/值對用冒號分割,而各個對用逗號分割,所有這些都包括在花括號中。

記住字典中的鍵/值對是沒有順序的。如果你想要一個特定的順序,那么你應該在使用前自己對它們排序。

字典是 dict 類的實例/對象。

使用字典

例 9.4 使用字典


    #!/usr/bin/python
    # Filename: using_dict.py

    # 'ab' is short for 'a'ddress'b'ook

    ab = {   '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' in ab: # OR ab.has_key('Guido')
    print "\nGuido's address is %s" % ab['Guido']

(源文件:code/using_dict.py

輸出


    $ 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

它如何工作

我們使用已經(jīng)介紹過的標記創(chuàng)建了字典 ab。然后我們使用在列表和元組章節(jié)中已經(jīng)討論過的索引操作符來指定鍵,從而使用鍵/值對。我們可以看到字典的語法同樣十分簡單。

我們可以使用索引操作符來尋址一個鍵并為它賦值,這樣就增加了一個新的鍵/值對,就像在上面的例子中我們對 Guido 所做的一樣。

我們可以使用我們的老朋友——del 語句來刪除鍵/值對。我們只需要指明字典和用索引操作符指明要刪除的鍵,然后把它們傳遞給 del 語句就可以了。執(zhí)行這個操作的時候,我們無需知道那個鍵所對應的值。

接下來,我們使用字典的 items 方法,來使用字典中的每個鍵/值對。這會返回一個元組的列表,其中每個元組都包含一對項目——鍵與對應的值。我們抓取這個對,然后分別賦給 for..in 循環(huán)中的變量 name 和 address 然后在 for -塊中打印這些值。

我們可以使用 in 操作符來檢驗一個鍵/值對是否存在,或者使用 dict 類的 has_key 方法。你可以使用 help(dict)來查看 dict 類的完整方法列表。

關鍵字參數(shù)與字典。如果換一個角度看待你在函數(shù)中使用的關鍵字參數(shù)的話,你已經(jīng)使用了字典了!只需想一下——你在函數(shù)定義的參數(shù)列表中使用的鍵/值對。當你在函數(shù)中使用變量的時候,它只不過是使用一個字典的鍵(這在編譯器設計的術語中被稱作 符號表 )。

序列

列表、元組和字符串都是序列,但是序列是什么,它們?yōu)槭裁慈绱颂貏e呢?序列的兩個主要特點是索引操作符和切片操作符。索引操作符讓我們可以從序列中抓取一個特定項目。切片操作符讓我們能夠獲取序列的一個切片,即一部分序列。

使用序列

例 9.5 使用序列


    #!/usr/bin/python
    # Filename: seq.py

    shoplist = ['apple', 'mango', 'carrot', 'banana']

    # Indexing or 'Subscription' operation
    print '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 list
    print '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 string
    name = '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[:]

(源文件:code/seq.py

輸出


    $ 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

它如何工作

首先,我們來學習如何使用索引來取得序列中的單個項目。這也被稱作是下標操作。每當你用方括號中的一個數(shù)來指定一個序列的時候,Python 會為你抓取序列中對應位置的項目。記住,Python 從 0 開始計數(shù)。因此,shoplist[0]抓取第一個項目,shoplist[3]抓取 shoplist 序列中的第四個元素。

索引同樣可以是負數(shù),在那樣的情況下,位置是從序列尾開始計算的。因此,shoplist[-1]表示序列的最后一個元素而 shoplist[-2]抓取序列的倒數(shù)第二個項目。

切片操作符是序列名后跟一個方括號,方括號中有一對可選的數(shù)字,并用冒號分割。注意這與你使用的索引操作符十分相似。記住數(shù)是可選的,而冒號是必須的。

切片操作符中的第一個數(shù)(冒號之前)表示切片開始的位置,第二個數(shù)(冒號之后)表示切片到哪里結(jié)束。如果不指定第一個數(shù),Python 就從序列首開始。如果沒有指定第二個數(shù),則 Python 會停止在序列尾。注意,返回的序列從開始位置 開始 ,剛好在 結(jié)束 位置之前結(jié)束。即開始位置是包含在序列切片中的,而結(jié)束位置被排斥在切片外。

這樣,shoplist[1:3]返回從位置 1 開始,包括位置 2,但是停止在位置 3 的一個序列切片,因此返回一個含有兩個項目的切片。類似地,shoplist[:]返回整個序列的拷貝。

你可以用負數(shù)做切片。負數(shù)用在從序列尾開始計算的位置。例如,shoplist[:-1]會返回除了最后一個項目外包含所有項目的序列切片。

使用 Python 解釋器交互地嘗試不同切片指定組合,即在提示符下你能夠馬上看到結(jié)果。序列的神奇之處在于你可以用相同的方法訪問元組、列表和字符串

參考

當你創(chuàng)建一個對象并給它賦一個變量的時候,這個變量僅僅 參考 那個對象,而不是表示這個對象本身!也就是說,變量名指向你計算機中存儲那個對象的內(nèi)存。這被稱作名稱到對象的綁定

一般說來,你不需要擔心這個,只是在參考上有些細微的效果需要你注意。這會通過下面這個例子加以說明。

對象與參考

例 9.6 對象與參考


    #!/usr/bin/python
    # Filename: reference.py

    print '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 object

    print 'Copy by making a full slice'
    mylist = shoplist[:] # make a copy by doing a full slice
    del mylist[0] # remove first item

    print 'shoplist is', shoplist
    print 'mylist is', mylist
    # notice that now the two lists are different

(源文件:code/reference.py

輸出


    $ 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)在程序的注釋中了。你需要記住的只是如果你想要復制一個列表或者類似的序列或者其他復雜的對象(不是如整數(shù)那樣的簡單 對象 ),那么你必須使用切片操作符來取得拷貝。如果你只是想要使用另一個變量名,兩個名稱都 參考 同一個對象,那么如果你不小心的話,可能會引來各種麻煩。

給 Perl 程序員的注釋
記住列表的賦值語句創(chuàng)建拷貝。你得使用切片操作符來建立序列的拷貝。

更多字符串的內(nèi)容

我們已經(jīng)在前面詳細討論了字符串。我們還需要知道什么呢?那么,你是否知道字符串也是對象,同樣具有方法。這些方法可以完成包括檢驗一部分字符串和去除空格在內(nèi)的各種工作。

你在程序中使用的字符串都是 str 類的對象。這個類的一些有用的方法會在下面這個例子中說明。如果要了解這些方法的完整列表,請參見 help(str)。

字符串的方法

例 9.7 字符串的方法


    #!/usr/bin/python
    # Filename: str_methods.py

    name = 'Swaroop' # This is a string object 

    if 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)

(源文件:code/str_methods.py

輸出


    $ 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 序列的項目的整潔的方法,它返回一個生成的大字符串。

概括

我們已經(jīng)詳細探討了多種 Python 內(nèi)建的數(shù)據(jù)結(jié)構(gòu)。這些數(shù)據(jù)結(jié)構(gòu)將是編寫程序時至關重要的部分。

現(xiàn)在我們已經(jīng)掌握了很多 Python 的基本知識,我們接下來將學習如何設計和編寫一個實用的 Python 程序。