《dinv into python》开始了解python
1.2. 聲明函數
象大多數其它語言,Python擁有函數。但是不象C++或 J ava,它沒有獨立的接口聲明和實現聲明。一旦需要一個函數,聲明它,編碼就行了。 根據上個例子: dive into python有寫道: def buildConnectionString(param s ):
有幾件事情需要注意的。首先,關鍵字 def 為函數聲明的開始。不象VB,Python并不區分有返回值的函數與無返回值的函數。它沒有子程序。全部都是函數,所有的函數都以 def 開始。
其次,函數沒有定義返回的數據類型。實際上,甚至不需要指定是否會返回一個值。函數并不關心第一種情況或第二種情況。如果函數執行了一個 return 語句,它將返回一個值,否則會返回 None (Python的空值)。
第三,參數 params 并不需要指明數據類型。在Python中,變量不需要被明確類型。Python會指出一個變量是什么類型,并在內部保持記錄。
?
1.3. 文檔化函數
可以通過給出一個文檔字符串文檔化一個Python函數。
例 1.4. 定義 buildConnectionString 函數的文檔字符串
def buildConnectionString(param s ):"""Build a connection string from a dictionary of parameters.Returns string."""三重雙引號的引用表示一個多行字符串。在定義一個文檔字符串的時候,你會看到它們經常被使用。
任何在三重雙引號中的東西都是函數的文檔字符串,它們用來說明函數可以做什么。如果存在文檔字符串,它必須要在函數中的被首先定義(也就是說在冒號后面被定義)。在技術上不需要給函數定義文檔字符串,但是你應該這樣做。我相信在你所參加過的每一個編程課上已經聽到過這一點,但是Python會給你一些其它的機制:文檔字符串在運行時可作為函數的屬性。
| 許多Python IDE使用文檔字符串來提供上下文相關提示,這樣當你敲入一個函數名,它的文檔字符串將顯示為提示框。這一點相當的有用,但是完全要看你寫的文檔字符串的好壞了。 1.4. 每個都是對象萬一你沒聽到,我剛才說了Python函數有屬性,那些屬性在運行時可用。 函數,如同在Python中的每個東西,是一個對象。 例 1.5. 存取 buildConnectionString 函數的文檔字符串 >>> import odbchelper>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"} >>> print odbchelper.buildConnectionString(params) server=mpilgrim;uid=sa;database=master;pwd=secret >>> print odbchelper.buildConnectionString.__doc__ Build a connection string from a dictionary Returns string. ? ?
在Python中每個東西都是對象,并且幾乎每個東西都有屬性和方法。[1] 所有的函數都有一個內置的屬性 __doc__,它會返回在函數源代碼中定義的文檔字符串。 這一點如此重要,所以我會在前幾講中重復它,以防你忘記了:在Python中的每個東西都是對象。字符串是對象。列表是對象。函數是對象。甚至模塊是對象,這一點我們很快會看到。
| |||||||
1.5. 縮排代碼
Python函數沒有明顯的 begin 或 end,或任何括號或大括號,可以標識函數從哪里開始,又在哪里結束。唯一的分隔是通過一個冒號(:)和代碼本身的縮排來表示。
例 1.6. 縮排 buildConnectionString 函數
def buildConnectionString(param s ):"""Build a connection string from a dictionary of parameters.Returns string."""return ";". join (["%s=%s" % (k, param s [k]) for k in param s .key s ()])代碼塊(函數,if 語句,for 循環,等等)通過它們的縮排來定義。縮排表示塊的開始,非縮排表示結束,不存在明顯的括號,大括號,或關鍵字。這就意味著空白是有意義的,并且要一致。在這個例子中,函數代碼(包括文檔字符串)縮近了4個空格。不一定非要是4個,只要一致就可以了。第一行沒有縮近,則不算在函數內。
在經過開始的一些反對和同Fortran相比后的挖苦之后,你將會心平氣和地對待它,開始理解它的好處。一個主要的好處是,所有的Python程序看上去差不多,因為縮排是語言的要求而不是風格問題。這樣就更容易閱讀和理解他人的Python代碼。
1.6. 測試模塊
Python模塊是對象,并且有幾個有用的屬性。在編寫模塊時,你可以利用這一點更容易地測試模塊。
例 1.7. if __name__ 技巧
if __name__ == "__main__":在開始學習好東西之前,有兩點要說明。第一,在 if 表達式周圍不需要小括號。第二,象C語言一樣,Python使用 == 進行比較,使用 = 進行賦值。不象C語言,Python不支持行內賦值,所以不存在把賦值當成比較的偶然情況。
那么為什么說這個特殊的 if 語句是一個技巧呢?模塊是對象,并且所有的模塊都有一個內置屬性 __name__。一個模塊的 __name__ 的值要看你如何使用它。如果 import 模塊,那么 __name__ 的值通常為模塊的文件名,不帶路徑或者文件擴展名。但是你也可以象一個標準的程序一樣直接運行模塊,在這種情況下 __name__ 的值將是一個特別的缺省值, __main__。
例 1.8. 一個導入模塊的 __name__
>>> import odbchelper>>> odbchelper.__name__ 'odbchelper'一旦了解這一點,你可以在模塊內部為你的模塊設計一個測試套件,通過在其中加入這個 if 語句。當你直接運行模塊, __name__ 的值是 __main__,所以測試套件執行。當你導入模塊, __name__ 的值就是別的東西了,所以測試套件被忽略。這樣使得在將新的模塊集成到一個大程序之前開發和調試容易多了。
| 在MacPython上,需要一個額外的步聚來使得 if __name__ 技巧有效。點擊窗口右上角的黑色三角,彈出模塊的屬性菜單,確認Run as __main__被選中。 | |
1.7. 字典 101
有必要先講些別的,因為你需要知道字典,序列(tuples),和列表。如果你一個Perl高手,你大概可以忽略關于字典和列表那一塊,但是你仍然應該對序列進行關心。
Python的內置數據類型之一是字典,它在關鍵字與值之間定義了一對一的關系。這一點就象Perl中的關聯數組,Java中的 Map ,或VBScipt中的 Scripting.Dictionary 對象。
例 1.9. 定義一個字典
>>> d = {"server":"mpilgrim", "database":"master"} >>> d {'server': 'mpilgrim', 'database': 'master'} >>> d["server"] 'mpilgrim' >>> d["database"] 'master' >>> d["mpilgrim"] Traceback (innermost last):File "<interactive input>", line 1, in ?KeyError: mpilgrim| 首先,我們創建了一個擁有兩個元素的新字典,并將其賦值給變量 d。每一個元素都是一個鍵-值對,整個元素集合用大括號括起來。 | |
| server 是一個鍵字,它所關聯的值為 mpilgrim,用 d["server"] 來引用。 | |
| database 是一個鍵字,它所關聯的值為 master,用 d["database"] 來引用。 | |
| 你可以通過鍵字來得到值,但是不能通過值得到鍵字。所以 d["server"] 為 mpilgrim,但是使用 d["mpilgrim"] 會引發一個異常,因為 mpilgrim 不是一個鍵字。 ? |
例 1.10. 修改一個字典
>>> d {'server': 'mpilgrim', 'database': 'master'} >>> d["database"] = "pubs" >>> d {'server': 'mpilgrim', 'database': 'pubs'} >>> d["uid"] = "sa" >>> d {'server': 'mpilgrim', 'uid': 'sa', 'database': 'pubs'}| 不能在一個字典中有重復的鍵字。給一個存在的鍵字賦值會抹掉原來的值。 | |
| 可以在任何時候加入新的鍵-值對。這種語法同修改存在的值一樣。(是的,它可能某天會給你帶來麻煩,你可能認為增加了新值,但實際上只是反復地修改了同樣的值,因為你的鍵字沒有按照你的想象改變。) |
注意新的元素(鍵字為 uid,值為 sa)出現在字典中間。實際上,它只不過是一種巧合,在第一個例子中的元素看上去是有序的。現在它們看上去無序了則更是一種巧合。
| 字典沒有元素順序的概念。說元素順序亂了是不正確的,它們只是簡單的無序。這是一個重要的特性,它會在你想要以一種特定的,可重復的順序(象以鍵字的字母表順序)存取字典元素的時候騷擾你。有一些實現的方法,它們只是沒有加到字典中去。 | |
例 1.11. 在字典中混用數據類型
>>> d {'server': 'mpilgrim', 'uid': 'sa', 'database': 'pubs'} >>> d["retrycount"] = 3 >>> d {'server': 'mpilgrim', 'uid': 'sa', 'database': 'master', 'retrycount': 3} >>> d[42] = "douglas" >>> d {'server': 'mpilgrim', 'uid': 'sa', 'database': 'master', 42: 'douglas', 'retrycount': 3}| 字典不是只用于字符串。字典的值可以是任意數據類型,包括字符串,整數,對象,或者甚至其它的字典。在一個單個字典里,字典的值并不需要全都是同一數據類型,可以根據需要混用和配匹。 | |
| 字典的關鍵字要嚴格一些,但是它們可以是字符串,整數和幾種其它的類型(后面還會談到這一點)。也可以在一個字典中混用和配匹關鍵字。 ? |
例 1.12. 從字典中刪除元素
>>> d {'server': 'mpilgrim', 'uid': 'sa', 'database': 'master', 42: 'douglas', 'retrycount': 3} >>> del d[42] >>> d {'server': 'mpilgrim', 'uid': 'sa', 'database': 'master', 'retrycount': 3} >>> d.clear() >>> d {}| del 允許你根據鍵字將單個元素從字典中刪除。 | |
| clear 會刪除一個字典中所有元素。注意空的大括號所表示的集合說明一個字典沒有元素。 |
自己運行的情況
1.8. 列表 101
列表是Python中使用最頻繁的數據類型。如果你對列表僅有的經驗是在VB中的數組或Java中的 Lists ,那么振作起來,面對Python列表吧。
例 1.13. 定義列表
>>> li = ["a", "b", "mpilgrim", "z", "example"] >>> li ['a', 'b', 'mpilgrim', 'z', 'example'] >>> li[0] 'a' >>> li[4] 'example'| 首先我們定義了一個有5個元素的列表。注意它們保持著它們初始的順序。這不是一個偶然。一個列表是一個用方括號包括的有序元素集。 | |
| 一個列表可以象一個以0開始的數組一樣使用。任何一個非空列表的第一個元素總是 li[0]。 | |
| 這個5元素列表的最后一個元素是 li[4],因為列表總是從0開始。 |
例 1.14. 負的列表索引
>>> li ['a', 'b', 'mpilgrim', 'z', 'example'] >>> li[-1] 'example' >>> li[-3] 'mpilgrim'| 負數索引從列表的尾部開始向后計數存取元素。任何一個非空的列表最后一個元素總是 li[-1]。 | |
| 如果負數索引使你感到糊涂,象這樣理解它:li[n] == li[n - len(li)]。所以在這個列表里,li[2] == li[2 - 5] == li[-3]. |
例 1.15. 分割一個列表
>>> li ['a', 'b', 'mpilgrim', 'z', 'example'] >>> li[1:3] ['b', 'mpilgrim'] >>> li[1:-1] ['b', 'mpilgrim', 'z'] >>> li[0:3] ['a', 'b', 'mpilgrim']| 你可以通過指定2個索引得到列表的子集,叫做一個“分片”。返回值是一個新的列表,它包含了列表中按順序從第一個分片索引(這里為 li[1])開始,直到但是不包括第二個分片索引(這里為 li[3])的所有元素。 | |
| 如果一個或兩個分片索引是負數,分片也可以工作。如果對你有幫助,你可以這樣理解:從左向右閱讀列表,第一個分片索引指定了你想要的第一個元素,第二個分片索引指定了第一個你不想要的元素。返回的值為在其間的每個元素。 | |
| 列表從0開始,所以 li[0:3] 返回列表的前3個元素,開始從 li[0],直到但不包括 li[3]。 |
例 1.16. 分片縮寫
>>> li ['a', 'b', 'mpilgrim', 'z', 'example'] >>> li[:3] ['a', 'b', 'mpilgrim'] >>> li[3:] ['z', 'example'] >>> li[:] ['a', 'b', 'mpilgrim', 'z', 'example']| 如果任一個分片索引為0,你可以將其省略,默認為0。所以 li[:3] 同前一個例子的 li[0:3] 一樣。 | |
| 注意這里的對稱寫法。在這個5元素列表中,li[:3] 返回前三個元素,而 li[3:] 返回后兩個元素。實際上,li[:n] 將總是返回前 n 個元素,而 li[n:] 將返回其它的元素。 | |
| 如果兩個分片索引均省略,將包括列表的所有元素。但是與原始的列表 li 不是同一個,它是一個新的列表,恰好擁有與 li 全部一樣的元素。li[:] 是生成一個列表拷貝的縮寫。 |
例 1.17. 向列表中增加元素
>>> li ['a', 'b', 'mpilgrim', 'z', 'example'] >>> li.append("new") >>> li ['a', 'b', 'mpilgrim', 'z', 'example', 'new'] >>> li.insert(2, "new") >>> li ['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new'] >>> li.extend(["two", "elements"]) >>> li ['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']| append 增加單個元素到列表的尾部。 | |
| insert 在列表中插入單個元素。數值參數是使得列表增加的第一個元素的索引(此句原文為:“The numeric argument is the index of the first element that gets bumped out of position.”,但實在不好翻譯,只暫時這樣翻譯,希望有什么好的建議。)。注意列表元素不需要唯一,現在有兩個獨立的元素擁有 new 這個值,li[2] 和 li[6]。 | |
| extend 連接列表。注意不要用多個參數調用 extend ,要使用一個列表參數調用。在這種情況下,列表有兩個元素。 ? |
例 1.18. 搜索列表
>>> li ['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements'] >>> li.index("example") 5 >>> li.index("new") 2 >>> li.index("c") Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: list.index(x): x not in list >>> "c" in li 0| index 在列表中查找值第一次的出現并返回索引值。 | |
| index 在列表中查找值 第一次 的出現。在本例中, new 在列表中出現了兩次,在 li[2] 和li[6],但是 index 將只返回第一個索引,2。 | |
| 如果在列表中沒有找到值,Python會引發一個異常。這一點與大部分的語言相當不同,大部分語言將會返回某個無效索引。盡管這種處理可能看上去令人討厭,它仍然是好東西,因為它說明你的程序會由于源代碼的問題而崩潰,好于在后面當你使用無效索引而引起崩潰。 | |
| 要測試一個值是否在列表內,使用 in,如果值找到了,它返回 1 ,或者沒找到則為 0 。 |
| 在Python中不存在布爾類型。在一個布爾上下文中(象 if 語句),0 是假,所有其它的數值為真。這一點也可以擴展到其它類型。一個空串(""),一個空列表([]),和一個空字典({})都是假,所有其它的字符串,列表,和字典是真。 | |
例 1.19. 從列表中除去元素
>>> li ['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements'] >>> li.remove("z") >>> li ['a', 'b', 'new', 'mpilgrim', 'example', 'new', 'two', 'elements'] >>> li.remove("new") >>> li ['a', 'b', 'mpilgrim', 'example', 'new', 'two', 'elements'] >>> li.remove("c") Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: list.remove(x): x not in list >>> li.pop() 'elements' >>> li ['a', 'b', 'mpilgrim', 'example', 'new', 'two']| remove 從列表中除掉第一次出現的值。 | |
| remove 僅 除掉第一次出現的值。在本例中,new 在列表中出現了兩次,但是 li.remove("new") 僅除掉了第一次出現的值。 | |
| 如果在列表中沒有找到值,Python引發一個異常。它反映了 index 方法的行為。 | |
| pop 是一個有趣的東西。它執行兩件事:除掉列表的最后一個元素,然后返回除掉的值。注意這一點同 li[-1]不同,后者返回一個值但不改變列表,也不同于 li.remove(value),后者改變列表但不返回值。 |
例 1.20. 列表操作符
>>> li = ['a', 'b', 'mpilgrim'] >>> li = li + ['example', 'new'] >>> li ['a', 'b', 'mpilgrim', 'example', 'new'] >>> li += ['two'] >>> li ['a', 'b', 'mpilgrim', 'example', 'new', 'two'] >>> li = [1, 2] * 3 >>> li [1, 2, 1, 2, 1, 2]| 列表也可以用 + 操作符連接起來。list = list + otherlist 相當于 list.extend(otherlist)。但是 + 操作符將連接后的列表作為一個值返回,而 extend 僅修改存在的列表。 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Python支持 += 操作符。li += ['two'] 相當于 li = li + ['two']。+= 操作符可用于列表,字符串,和整數,并且它也可以在用戶定義類中被重載。(第三章會有更多的類) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| * 操作符作為一個重復符可用在列表上。li = [1, 2] * 3 相當于 li = [1, 2] + [1, 2] + [1, 2], 將三個列表連成一個。 ? 1.9. 序列 101序列是不可變列表。一旦創建了一個序列就不能以任何方式改變它。 例 1.21. 定義序列 >>> t = ("a", "b", "mpilgrim", "z", "example") >>> t ('a', 'b', 'mpilgrim', 'z', 'example') >>> t[0] 'a' >>> t[-1] 'example' >>> t[1:3] ('b', 'mpilgrim')
例 1.22. 序列沒有方法 >>> t ('a', 'b', 'mpilgrim', 'z', 'example') >>> t.append("new") Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'append' >>> t.remove("z") Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'remove' >>> t.index("example") Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'index' >>> "z" in t 1
那么序列有什么好處呢?
1.10. 定義變量即然你認為已經了解了字典,序列和列表的所有知識,就讓我們回到我們的例子程序 odbchelper.py。 Python象大多數其它語言一樣有局部和全局變量,但是它沒有明顯的變量聲明。變量通過賦值產生,當超出作用范圍時自動消滅。 例 1.23. 定義 myParams 變量 if __name__ == "__main__":myParam s = {"server":"mpilgrim", \"database":"master", \"uid":"sa", \"pwd":"secret" \}這里有幾個有趣的地方。首先,注意一下縮排。if 語句是代碼塊,需要象函數一樣縮排。 其次,變量的賦值是一條命令被分成了幾行,用反斜線(“\”)作為續行符。
第三,你從未聲明過變量 myParams,你只是給它賦了一個值。這點就象是VBScript沒有設置 option explicit 選項。幸運的是,不象VBScript,Python不允許你引用一個未被賦值的變量,試圖這樣做會引發一個異常。 例 1.24. 引用未賦值的變量 >>> x Traceback (innermost last): File "<interactive input>", line 1, in ? NameError: There is no variable named 'x' >>> x = 1 >>> x 1早晚有一天你會為此而感謝Python。
1.11. 格式化字符串odbchelper.py 所有實際的工作是用一行代碼完成的,下面就是。 return ";". join (["%s=%s" % (k, param s [k]) for k in param s .key s ()])不要恐慌。忽略別的東西,集中在中間部分,它是字符串格式化表達式。(如果你是一個C高手,也許可以忽略這部分。) 例 1.25. 中間部分 "%s=%s" % (k, param s [k])Python支持將值的格式化輸出到字符串中,象C語言中的 sprintf 函數。最基本的用法是簡單地在 %s 占位符的地方插入一個值。 例 1.26. 字符串格式化介紹 >>> params = {"uid":"sa", "pwd":"secret"} >>> k = "uid" >>> "%s=%s" % (k, params[k]) 'uid=sa' >>> k = "pwd" >>> "%s=%s" % (k, params[k]) 'pwd=secret'
注意(k,params[k])是一個序列。我說過它們對某些東西有用。 你可能一直在想做了這么多工作只是為了做簡單的字符串連接,你想的不錯;只不過字符串格式化不只是連接。它甚至不僅僅是格式化。它也是強制類型轉換。 例 1.27. 字符串格式化對比字符串連接 >>> uid = "sa" >>> pwd = "secret" >>> print pwd + " is not a good password for " + uid secret is not a good password for sa >>> print "%s is not a good password for %s" % (pwd, uid) secret is not a good password for sa >>> userCount = 6 >>> print "Users connected: %d" % (userCount, ) Users connected: 6 >>> print "Users connected: " + userCount Traceback (innermost last):File "<interactive input>", line 1, in ?TypeError: cannot add type "int" to string
1.13. 連接列表和分割字符串你有了一個形如 key=value 的鍵-值對列表,并且想將它們合成為單個字符串。為了將任意字符串列表連接成單個字符串,使用一個字符串對象的 join 方法。 例 1.32. 在 buildConnectionString 中連接字符串 return ";". join (["%s=%s" % (k, param s [k]) for k in param s .key s ()])在我們繼續之前有一個有趣的地方。我一直在重復函數是對象,字符串是對象,每個東西都是對象。你也許認為我的意思是說字符串 變量 是對象。但是不,仔細地看一下這個例子,你將會看到字符串 ";" 本身是一個對象,你在調用它的 join 方法。 總之, join 方法將列表元素連接成單個字符串,每個元素用一個分號隔開。分隔符不需要是一個分號;它甚至不必是單個字符。它可以是任何字符串。
例 1.33. odbchelper.py 的輸出 >>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"} >>> ["%s=%s" % (k, params[k]) for k in params.keys()] ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret'] >>> ";".join(["%s=%s" % (k, params[k]) for k in params.keys()]) server=mpilgrim;uid=sa;database=master;pwd=secret接著,上面的字符串從 help 函數返回,被調用塊打印出來,這樣就給出在你開始閱讀本章時令你感到吃驚的輸出。 歷史記錄 當我開始學Python時,我以為 join 應該是列表的方法,它會使用分隔符作為一個參數。看上去有些矛盾的原因純粹由于歷史造成的。在Python 1.6之前,字符串完全沒有這些有用的方法。有一個獨立的 string 模塊擁有所有的字符串函數,每個函數使用一個字符串作為它的第一個參數。這些函數被認為足夠重要,所以它們移到字符串中去了,這當然是件好事情。但是,無論好壞, join 跟它們一起,這就是我們看到的。 你可能在想是否存在一個適當的方法來將字符串分割成一個列表。當然有,它叫做 split。 例 1.34. 分割字符串 >>> li = ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret'] >>> s = ";".join(li) >>> s 'server=mpilgrim;uid=sa;database=master;pwd=secret' >>> s.split(";") ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret'] >>> s.split(";", 1) ['server=mpilgrim', 'uid=sa;database=master;pwd=secret']
?
1.14. 小結odbchelper.py 程序和它的輸出現在應該非常清楚了。 例 1.35. odbchelper.py def buildConnectionString(param s ):"""Build a connection string from a dictionary of parameters.Returns string."""return ";". join (["%s=%s" % (k, param s [k]) for k in param s .key s ()])if __name__ == "__main__":myParam s = {"server":"mpilgrim", \"database":"master", \"uid":"sa", \"pwd":"secret" \}print buildConnection S tring(myParam s )例 1.36. odbchelper.py 的輸出 server=mpilgrim;uid=sa;database=master;pwd=secret在深入下一章之前,確保你可以無困難地完成下面的事情:
? 下面第一章已經完畢,大體上懂得python是什么玩意 | ||||||||||||||||||||||||||||||||||||||||||||||||||
轉載于:https://www.cnblogs.com/nickchan/archive/2011/08/18/3104550.html
總結
以上是生活随笔為你收集整理的《dinv into python》开始了解python的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS2008 Tips #008 如何创
- 下一篇: python基础--GIL全局解释器锁、