字典和列表
在字典中,列表可以作為值出現。
例如,當倒轉字典的時候,可能有的鍵對應的值,就是由列表組成的
def
invert_dict
(d):
inverse =
dict()
for key in d:
val = d[key]
if val not
in inverse:
inverse[val]
=[key]
else
: inverse[val]
return inverse
每次迴圈,key從d獲得乙個鍵和相應的值val。如果val不在inverse中,意味著我們之前沒有見過它,因此我們生成乙個新項並用乙個單元素集合來初始化列表。
列表可以作為字典中的值,但是不可以是鍵
字典使用雜湊表實現,這意味著鍵必須是可雜湊的
雜湊函式接受乙個值並返回乙個正數。
字典使用被稱作雜湊值的這些整數,來儲存和查詢鍵值對
如果鍵是不可變的,那麼這種實現可以很好地工作。
如果鍵是可變的,例如列表,就會發生不好的事情。
例如,當生成乙個鍵值對時,python雜湊該鍵並將其儲存在相應的位置。如果改變鍵然後再次雜湊,對應的值就將被儲存到另乙個位置,字典將不會正確的工作。
字典也是可變的,所以它們不能作為鍵,但是可以用作值。
備忘錄避免執行程式時,同一形參被多次運算,隨著引數的增加,運算量增大,執行效率會很低。
乙個解決方法是儲存已經計算過的值,將它們存在乙個字典中。儲存之前計算過的值以便今後使用,它被稱為備忘錄
下面使用備忘錄實現fibonacci功能
known =
deffibonacci
(n):
if n in known:
return known[n]
res = fibonacci(n-1)
+ fibonacci(n-2)
known[n]
= res
return res
known初始化儲存了兩個已知的斐波那契數字
當函式被呼叫時,會先檢查對應序列的斐波那契數列是否已經有計算好的值,這樣就不用了重複進行迭代
如果當前序列對應的值還沒有被計算過,那麼就會在字典中加入新的項
這樣可以很好地提公升執行速度
全部變數
在上例中,known是在函式的外部建立的,因此它屬於被稱作_main_的特殊幀。因為它裡面的變數可以被任意函式訪問,它們也被稱為全域性變數。與函式結束就會消失的區域性變數不一樣,不同函式呼叫時全域性變數一直都存在。
全域性變數普遍用作標記
例如,一些程式使用乙個被稱作verbose的標記來控制輸出的豐富程度:
verbose =
true
defexamples()
:if verbose:
print
('running example1'
)
been_called =
false
defexample2()
: been_called =
true
執行後會發現,beencalled的值並為發生改變,原因在於這個語句其實相當於,建立了乙個新的區域性變數,函式執行結束後,區域性變數也會消失,對全域性變數並沒有影響
要在函式內對全域性變數重新賦值,必須在使用前宣告該全域性變數:
been_called =
false
defexample2()
:global been_called
been_called =
true
global語句告訴變歧義,在該函式中,該變數名指的都是全域性變數,不要生成區域性變數
如果全域性變數是可變的,可以不加宣告的修改它
known =
defexample4()
: known[2]
=1
所以可以不加宣告的增加刪除和替代全域性列表或字典中的元素,因為這些操作的基礎是,該變數已被初始化,所以會自動去找全域性變數。
但是如果想對全域性變數重新賦值,就必須宣告
def
example5()
:global known
known =
dict
()
除錯
除錯大資料集的建議
縮小輸入:
如果可能,減小資料結合的大小,例如文字檔案,先讀取前幾行,在查詢和解決錯誤的同時,逐步增加n的值
檢查摘要和型別:
列印重要的只要,而不是全部資料集合
例如字典或列表中元素的數目
執行時錯誤的乙個常見原因是,值的型別不正確。通常列印值的型別就夠了
編寫自檢**:
例如,編寫計算平均值的程式,檢查運算結果與列表中最大最小的值的關係。這被稱作合理性檢測,因為能檢測出不合理的結果
另一種檢查是比較兩個不同計算的結果,檢視是否一致,這被稱為一致性檢查
格式化輸出:
格式化除錯輸出能夠更容易定位乙個錯誤。
pprint模組提供了乙個pprint函式,它可以更可讀的格式顯示內建型別
print輸出結果都在一行,不方便檢視
pprint採用分行列印輸出,列印出來的資料結構更加完整
元組元組是不可變的
元組是一組值的序列,其中的值可以是任意的型別,使用整數索引,因此從這點上看,元組和列表非常相似,二者不同之處在於元組的不可變性
t =
('a'
,'c'
,'d'
)
雖然並非必須,元組通常用括號括起來,用逗號間隔開
使用單一元素建立元組時,需要在結尾處新增乙個逗號
t1 =
'a',
將值放置在括號中並不會建立元組
t2 =
('a'
)>>
>
type
(t2)
>
str
另乙個建立元組的方法是使用內建函式tuple。在沒有引數傳遞時,它會建立乙個空元組:
t =
tuple
()
如果實參是乙個序列(字串,列表或者元組),結果將是乙個包含序列內元素的元組
t =
tuple
('lupins'
)>>
>t
>
('l'
,'u'
,'p'
,'i'
,'n'
,'s'
)
因為tuple是內建函式名,所以應該避免將它用作變數名
列表中的大多數操作符也同樣適用於元組,方括號運算度將索引乙個元素
t[
0]
切片運算子選取乙個範圍內的元素
t[1:
3]
如果試圖修改元組中的乙個元素,會得到錯誤資訊
因為元組是不可變的,無法改變其中的元素,但是可以使用其他元組替換現有元組
t =
('a',)
+ t[1:
]
關係運算子也適用於元組和其他徐磊,python會首先比較序列中的第乙個元素,如果它們相等,就繼續比較下一組元素,以此類推,直至比值不同。在它之後的元素,可不會再參與比較
(0,
1,2000000
)<(0
,3,4
)
元組賦值
兩個變數互換值的操作,傳統方法需要使用乙個臨時變數
但是為了簡便,可以通過元祖賦值來實現
a,b = b,a
等號左側是變數組成的元組,右側是表示式組成的元組。每個值都被賦給了對應的變數。變數被重新賦值之前,將先對右側的表示式進行求值。
左側變數數和右側值的數目必須相同
一般來說,右側可以是任意型別的序列。
例:可以將乙個電子郵箱分為使用者名稱和網域名稱
addr =
uname,domain = addr.split(
'@')
split返回的物件,是乙個有兩個元素的列表,列表裡的值,被分別賦給了兩個變數 think python學習筆記(5)
鏈式條件 當有多個可能的時候,我們需要多個分支 表示這種情況的方法之一是鏈式條件 if x y print 0 elif xprint 1 else print 2 elif是else if的縮寫,elif語句數目沒有限制,如果只有乙個else1從句,那麼這個從句必須在最末,但這個語句並不是必須的 ...
think python學習筆記(6)
增量式開發 面對複雜的程式,可以採用增量式開發 增量式開發的目標是通過每次只增加和測試少量 來避免長時間的除錯 這種開發而關鍵在於 1.從乙個能執行的程式開始,每次只增加少量改動 2.用臨時變數儲存中間值,便於檢查 3.刪除腳手架 組合寫乙個函式,接受兩個點作為引數,分別是圓心和圓周上一點,然後計算...
think python學習筆記(7)
平方根 迴圈常用於計算數值的程式中,這類程式一般從乙個大概的值開始,然後迭代式的進行改進 例如,牛頓法是計算平方根的一種方法 當我們想求a的平方根時,從任意乙個估算值開始x,利用下面的公式可以計算出更為精確地估算值 y x a x 2 得到的y的值會更加接近平方根的真實值,不斷的用y去代替x,利用這...