Note One:about sequences and lists
序列是不可變列表。一旦創(chuàng)建了一個(gè)序列就不能以任何方式改變它。
例 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')
|
序列的定義同列表的定義方式相同,除了整個(gè)元素集是用小括號(hào)包圍的而不是方括號(hào)。
|
|
序列的元素象列表一樣按定義的次序進(jìn)行排序。序列的索引象列表一樣從0開(kāi)始,所以一個(gè)非空序列的第一個(gè)元素總是 t[0]。
|
|
負(fù)數(shù)索引象列表一樣從序列尾部開(kāi)始計(jì)數(shù)。
|
|
分片也可以使用,就象列表一樣。注意當(dāng)分割一個(gè)列表時(shí),會(huì)得到一個(gè)新的列表;當(dāng)分割一個(gè)序列時(shí),會(huì)得到一個(gè)新的序列。
|
例 1.22. 序列沒(méi)有方法?
>>>?
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???
|
你不能向序列增加元素。序列沒(méi)有 append 或 extend 方法。
|
|
你不能從序列中除掉元素。序列沒(méi)有 remove 或 pop 方法。
|
|
你不能在序列中查找元素。序列沒(méi)有 index 方法。
|
|
然而,你可以使用 in 來(lái)看一看是否一個(gè)元素存在于序列中。
|
那么序列有什么好處呢?
-
序列比列表操作速度快。如果你定義了一個(gè)值集合常量,并且唯一要用它做的是不斷地遍歷它,使用序列代替列表。
-
記得我說(shuō)過(guò)
字典關(guān)鍵字
可以是整數(shù),字符串和“幾種其它的類(lèi)型”嗎?序列就是那些類(lèi)型之一。序列可以在字典中被用作關(guān)鍵字,但是列表不行。[2]
-
序列用在字符串格式化,這一點(diǎn)我們會(huì)很快看到。
Note Two : Mapping in the Lists
列表映射介紹?
??????
>>>??li = [1, 9, 8, 4]
>>>??[elem*2 for elem in li]????? 
[2, 18, 16, 8]
>>>??li?????????????????????
[1, 9, 8, 4]
|
為了對(duì)這一點(diǎn)有一個(gè)感性認(rèn)識(shí),從右向左看它。 li 是一個(gè)將要映射的列表。Python循環(huán)遍歷 li 一次一個(gè)元素,臨時(shí)將每個(gè)元素的值賦給變量 elem。然后Python使用函數(shù) elem*2 ,接著將結(jié)果追加到返回列表中。
|
|
注意列表映射不改變被映射的列表。
|
Note Three :好東西?lambda?函數(shù)
Python支持一種有趣的語(yǔ)法,它允許你快速定義單行的最小函數(shù)。這些叫做 lambda 的函數(shù)是從Lisp中借用來(lái)的,可以被用在任何需要函數(shù)的地方。
出于歷史的原因,lambda 函數(shù)的語(yǔ)法與通常的函數(shù)有些細(xì)微的不同。
例 2.20. lambda 函數(shù)介紹
>>>
def
f(x):?????????
...????
return x*2
...????
>>>
f(3)
6
>>>
g = lambda x: x*2?
>>>
g(3)
6
>>>
(lambda x: x*2)(3)
6
|
這是一個(gè)通常的函數(shù)聲明,盡管以前你可能沒(méi)有看到過(guò)定義在交互式窗口中的函數(shù)。這個(gè) ... 說(shuō)明它是一個(gè)多行的交互語(yǔ)句。只要在第一行的后面敲入回車(chē),Python IDE會(huì)讓你接著輸入命令。
|
|
這是一個(gè) lambda 函數(shù),它完成同上面普通函數(shù)相同的事情。注意這里的簡(jiǎn)短的語(yǔ)法;沒(méi)有小括號(hào), return 是默認(rèn)的,并且函數(shù)沒(méi)有名字,只有將它賦值給變量的變量名。
|
|
你甚至可以不將 lambda 函數(shù)賦值給一個(gè)變量而使用它。這不是舉世無(wú)雙的東西,它只是展示了 lambda 函數(shù)只是一個(gè)內(nèi)聯(lián)函數(shù)。
|
總之, lambda 函數(shù)是一個(gè)可以接收任意多個(gè)參數(shù)(包括
可選參數(shù)
)并且返回單個(gè)表達(dá)式值的函數(shù)。 lambda 函數(shù)不能包含命令,它們所包含的表達(dá)式不能超過(guò)一個(gè)。不要試圖向 lambda 函數(shù)中塞入太多的東西;如果你需要更復(fù)雜的東西,應(yīng)該定義一個(gè)普通函數(shù),然后想讓它多長(zhǎng)就多長(zhǎng)。
|
lambda 函數(shù)是風(fēng)格問(wèn)題。不一定非要使用它們,任何能夠使用它們的地方,都可以定義一個(gè)分離的普通的函數(shù),用它來(lái)替換。我將它們用在需要封裝特殊的,非重用的代碼上,用許多小的一行函數(shù)不會(huì)弄亂我的代碼。
|
例 2.21. 在 in apihelper.py 中的 lambda 函數(shù)?
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
順便這里有幾件事情需要注意。首先,我們使用了
and-or
技巧的簡(jiǎn)單形式,沒(méi)問(wèn)題,因?yàn)橐粋€(gè) lambda 函數(shù)
在一個(gè)布爾環(huán)境下
總為真。(這并不意味著 lambda 函數(shù)不能返回假值。函數(shù)本身總是為真,它的返回值可以為任何值。)
第二,我們使用了 split 函數(shù)沒(méi)帶參數(shù)。你已經(jīng)看到過(guò)它帶
1個(gè)或2個(gè)參數(shù)
的使用,但是不帶參數(shù)它按空白進(jìn)行分割。
例 2.22. split 不帶參數(shù)????
>>>s = "this?? is\na\ttest"???????? 
>>>print s??
?this?? is
a test
>>>print s.split()????? 
['this', 'is', 'a', 'test']
>>>print???" ".join(s.split())??????? 
'this is a test'????
|
這是一個(gè)多行字符串,通過(guò)轉(zhuǎn)義字符的定義代替了
三重引號(hào)
。 \n 是一個(gè)回車(chē); \t 是一個(gè)制表符。
|
|
split 不帶參數(shù)按空白進(jìn)行分割。所以三個(gè)空格,一個(gè)回車(chē),和一個(gè)制表符都是一樣的。
|
|
你可以將空白統(tǒng)一化,通過(guò)分割一個(gè)字符串,然后用單個(gè)空格作為分隔符將其重新接起來(lái)。這就是 help 函數(shù)所做的,將多行文檔字符串合并成單行。
|
那么 help 函數(shù)到底用這些 lambda 函數(shù), split 函數(shù),和 and-or 技巧做了什么呢?
例 2.23. 將函數(shù)賦給一個(gè)變量
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
processFunc 現(xiàn)在是一個(gè)函數(shù),但它為哪一個(gè)函數(shù)要看 collapse 變量的值。如果 collapse 為真, processFunc(string) 將壓縮空白;否則,processFunc(string) 將返回未改變的參數(shù)。
在一個(gè)不很建壯的語(yǔ)言實(shí)現(xiàn)它,象VB,你將可能創(chuàng)建一個(gè)函數(shù),它接收一個(gè)字符串和一個(gè) collapse 參數(shù),使用一個(gè) if 語(yǔ)句來(lái)判斷是否要壓縮空白或不壓縮,然后返回相應(yīng)的值。這樣效率低,因?yàn)楹瘮?shù)將不得不處理每種可能性;每次你調(diào)用它,它將不得不在給出你所想要的東西之前,判斷是否要壓縮空白。在Python中,你可以將那種判斷邏輯拿到函數(shù)外面,而定義一個(gè)裁減過(guò)的 lambda 函數(shù)來(lái)給出確切的(并且唯一)你想要的。這樣做更有效率,更漂亮,并且更少導(dǎo)致那些令人討厭的(哦,想到那些參數(shù)就頭昏)的錯(cuò)誤。