think python學習筆記(12)

2021-10-07 06:11:30 字數 4293 閱讀 3559

字典和列表

在字典中,列表可以作為值出現。

例如,當倒轉字典的時候,可能有的鍵對應的值,就是由列表組成的

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 =

'[email protected]'

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,利用這...