網(wǎng)站性能檢測(cè)評(píng)分
注:本網(wǎng)站頁(yè)面html檢測(cè)工具掃描網(wǎng)站中存在的基本問(wèn)題,僅供參考。
python能做什么東西
用Python入門(mén)不明覺(jué)厲的馬爾可夫鏈蒙特卡羅(附案例代碼) 推廣視頻課程
大數(shù)據(jù)文摘作品
編譯:Niki、張南星、Shan LIU、Aileen
這篇文章讓小白也能讀懂什么是人們常說(shuō)的Markov Chain Monte Carlo。
在過(guò)去幾個(gè)月里,我在數(shù)據(jù)科學(xué)的世界里反復(fù)遇到一個(gè)詞:馬爾可夫鏈蒙特卡洛(Markov Chain Monte Carlo , MCMC)。在我的研究室、podcast和文章里,每每遇到這個(gè)詞我都會(huì)“不明覺(jué)厲”地點(diǎn)點(diǎn)頭,覺(jué)得這個(gè)算法聽(tīng)起來(lái)很酷,但每次聽(tīng)人提起也只是有個(gè)模模糊糊的概念。
我屢次嘗試學(xué)習(xí)MCMC和貝葉斯推論,而一拿起書(shū),又很快就放棄了。無(wú)奈之下,我選擇了學(xué)習(xí)任何新東西最佳的方法:應(yīng)用到一個(gè)實(shí)際問(wèn)題中。
通過(guò)使用一些我曾試圖分析的睡眠數(shù)據(jù)和一本實(shí)操類(lèi)的、基于應(yīng)用教學(xué)的書(shū)(《寫(xiě)給開(kāi)發(fā)者的貝葉斯方法》,我最終通過(guò)一個(gè)實(shí)際項(xiàng)目搞明白了MCMC。
《寫(xiě)給開(kāi)發(fā)者的貝葉斯方法》
https://github/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers
和學(xué)習(xí)其他東西一樣,當(dāng)我把這些技術(shù)性的概念應(yīng)用于一個(gè)實(shí)際問(wèn)題中而不是單純地通過(guò)看書(shū)去了解這些抽象概念,我更容易理解這些知識(shí),并且更享受學(xué)習(xí)的過(guò)程。
這篇文章介紹了馬爾可夫鏈蒙特卡洛在Python中入門(mén)級(jí)的應(yīng)用操作,這個(gè)實(shí)際應(yīng)用最終也使我學(xué)會(huì)使用這個(gè)強(qiáng)大的建模分析工具。
此項(xiàng)目全部的代碼和數(shù)據(jù):
https://github/WillKoehrsen/ai-projects/blob/master/bayesian/bayesian_inference.ipynb
這篇文章側(cè)重于應(yīng)用和結(jié)果,因此很多知識(shí)點(diǎn)只會(huì)粗淺的介紹,但對(duì)于那些想了解更多知識(shí)的讀者,在文章也嘗試提供了一些學(xué)習(xí)鏈接。
案例簡(jiǎn)介
我的智能手環(huán)在我入睡和起床時(shí)會(huì)根據(jù)心率和運(yùn)動(dòng)進(jìn)行記錄。它不是100%準(zhǔn)確的,但現(xiàn)實(shí)世界中的數(shù)據(jù)永遠(yuǎn)不可能是完美的,不過(guò)我們依然可以運(yùn)用正確的模型從這些噪聲數(shù)據(jù)提取出有價(jià)值的信息。
典型睡眠數(shù)據(jù)
這個(gè)項(xiàng)目的目的在于運(yùn)用睡眠數(shù)據(jù)建立一個(gè)能夠確立睡眠相對(duì)于時(shí)間的后驗(yàn)分布模型。由于時(shí)間是個(gè)連續(xù)變量,我們無(wú)法知道后驗(yàn)分布的具體表達(dá)式,因此我們轉(zhuǎn)向能夠近似后驗(yàn)分布的算法,比如馬爾可夫鏈蒙特卡洛(MCMC)。
選擇一個(gè)概率分布
在我們開(kāi)始MCMC之前,我們需要為睡眠的后驗(yàn)分布模型選擇一個(gè)合適的函數(shù)。一種簡(jiǎn)單的做法是觀察數(shù)據(jù)所呈現(xiàn)的圖像。下圖呈現(xiàn)了當(dāng)我入睡時(shí)時(shí)間函數(shù)的數(shù)據(jù)分布。
睡眠數(shù)據(jù)
每個(gè)數(shù)據(jù)點(diǎn)用一個(gè)點(diǎn)來(lái)表示,點(diǎn)的密度展現(xiàn)了在固定時(shí)刻的觀測(cè)個(gè)數(shù)。我的智能手表只記錄我入睡的那個(gè)時(shí)刻,因此為了擴(kuò)展數(shù)據(jù),我在每分鐘的兩端添加了數(shù)據(jù)點(diǎn)。如果我的手表記錄我在晚上10:05入睡,那么所有在此之前的時(shí)間點(diǎn)被記為0(醒著),所有在此之后的時(shí)間點(diǎn)記為1(睡著)。這樣一來(lái),原本大約60夜的觀察量被擴(kuò)展成11340個(gè)數(shù)據(jù)點(diǎn)。
可以看到我趨向于在10:00后幾分鐘入睡,但我們希望建立一個(gè)把從醒到入睡的轉(zhuǎn)變用概率進(jìn)行表達(dá)的模型。我們可以用一個(gè)簡(jiǎn)單的階梯函數(shù)作為模型,在一個(gè)精確時(shí)間點(diǎn)從醒著(0)變到入睡(1),但這不能代表數(shù)據(jù)中的不確定性。
我不會(huì)每天在同一時(shí)間入睡,因此我們需要一個(gè)能夠模擬出這個(gè)個(gè)漸變過(guò)程的函數(shù)來(lái)展現(xiàn)變化當(dāng)中的差異性。在現(xiàn)有數(shù)據(jù)下最好的選擇是logistic函數(shù),在0到1之前平滑地移動(dòng)。下面這個(gè)公式是睡眠狀態(tài)相對(duì)時(shí)間的概率分布,也是一個(gè)logistic公式。
在這里,β (beta) 和 α (alpha) 是模型的參數(shù),我們只能通過(guò)MCMC去模擬它們的值。下面展示了一個(gè)參數(shù)變化的logistic函數(shù)。
一個(gè)logistic函數(shù)能夠很好的擬合數(shù)據(jù),因?yàn)樵趌ogistic函數(shù)中入睡的概率在逐漸改變,捕捉了我睡眠模式的變化性。我們希望能夠帶入一個(gè)具體的時(shí)間t到函數(shù)中,從而得到一個(gè)在0到1之間的睡眠狀態(tài)的概率分布。我們并不會(huì)直接得到我是否在10:00睡著了的準(zhǔn)確答案,而是一個(gè)概率。創(chuàng)建這個(gè)模型,我們通過(guò)數(shù)據(jù)和馬爾可夫鏈蒙特卡洛去尋找最優(yōu)的alpha和beta系數(shù)估計(jì)。
馬爾可夫鏈蒙特卡洛
馬爾可夫鏈蒙特卡羅是一組從概率分布中抽樣,從而建立最近似原分布的函數(shù)的方法。因?yàn)槲覀儾荒苤苯尤ビ?jì)算logistic分布,所以我們?yōu)橄禂?shù)(alpha 和 beta)生成成千上萬(wàn)的數(shù)值-被稱為樣本-去建立分布的一個(gè)模擬。MCMC背后的基本思想就是當(dāng)我們生成越多的樣本,我們的模擬就更近似于真實(shí)的分布。
馬爾可夫鏈蒙特卡洛由兩部分組成。蒙特卡洛代表運(yùn)用重復(fù)隨機(jī)的樣本來(lái)獲取一個(gè)準(zhǔn)確答案的一種模擬方法。蒙特卡洛可以被看做大量重復(fù)性的實(shí)驗(yàn),每次更改變量的值并觀察結(jié)果。通過(guò)選擇隨機(jī)的數(shù)值,我們可以在系數(shù)的范圍空間,也就是變量可取值的范圍,更大比例地探索。下圖展示了在我們的問(wèn)題中,一個(gè)使用高斯分布作為先驗(yàn)的系數(shù)空間。
能夠清楚地看到我們不能在這些圖中一一找出單個(gè)的點(diǎn),但通過(guò)在更高概率的區(qū)域(紅色)進(jìn)行隨機(jī)抽樣,我們就能夠建立最近似的模型。
馬爾可夫鏈(Markov Chain)
馬爾可夫鏈?zhǔn)且粋€(gè)“下個(gè)狀態(tài)值只取決于當(dāng)前狀態(tài)”的過(guò)程。(在這里,一個(gè)狀態(tài)指代當(dāng)前時(shí)間系數(shù)的數(shù)值分配)。一個(gè)馬爾可夫鏈?zhǔn)恰敖⊥钡?,因?yàn)槿绾蔚竭_(dá)當(dāng)前狀態(tài)并不要緊,只有當(dāng)前的狀態(tài)值是關(guān)鍵。如果這有些難以理解的話,讓我們來(lái)設(shè)想一個(gè)每天都會(huì)經(jīng)歷的情景--天氣。
如果我們希望預(yù)測(cè)明天的天氣,那么僅僅使用今天的天氣狀況我們就能夠得到一個(gè)較為合理的預(yù)測(cè)。如果今天下雪,我們可以觀測(cè)有關(guān)下雪后第二天天氣的歷史數(shù)據(jù)去預(yù)測(cè)明天各種天氣狀況的可能性。馬爾可夫鏈的定義就是我們不需要知道一個(gè)過(guò)程中的全部歷史狀態(tài)去預(yù)測(cè)下一節(jié)點(diǎn)的狀態(tài),這種近似在許多現(xiàn)實(shí)問(wèn)題中都很有用。
把馬爾可夫鏈(Markov Chain)和蒙特卡洛(Monte Carlo),兩者放到一起,就有了MCMC。MCMC是一種基于當(dāng)前值,重復(fù)為概率分布系數(shù)抽取隨機(jī)數(shù)值的方法。每個(gè)樣本都是隨機(jī)的,但是數(shù)值的選擇也受當(dāng)前值和系數(shù)先驗(yàn)分布的影響。MCMC可以被看做是一個(gè)最終趨于真實(shí)分布的隨機(jī)游走。
為了能夠抽取alpha 和 beta的隨機(jī)值,我們需要為每個(gè)系數(shù)假設(shè)一個(gè)先驗(yàn)分布。因?yàn)槲覀儧](méi)有對(duì)于這兩個(gè)系數(shù)的任何假設(shè),我們可以使用正太分布作為先驗(yàn)。正太分布,也稱高斯分布,是由均值(展示數(shù)據(jù)分布),和方差(展示離散性)來(lái)定義的。下圖展示了多個(gè)不同均值和離散型的正態(tài)分布。
具體的MCMC算法被稱作Metropolis Hastings。為了連接我們的觀察數(shù)據(jù)到模型中,每次一組隨機(jī)值被抽取,算法將把它們與數(shù)據(jù)進(jìn)行比較。一旦它們與數(shù)據(jù)不吻合(在這里我簡(jiǎn)化了一部分內(nèi)容),這些值就會(huì)被舍棄,模型將停留在當(dāng)前的狀態(tài)值。
如果這些隨機(jī)值與數(shù)據(jù)吻合,那么這些值就被接納為各個(gè)系數(shù)新的值,成為當(dāng)前的狀態(tài)值。這個(gè)過(guò)程會(huì)有一個(gè)提前設(shè)置好的迭代次數(shù),次數(shù)越多,模型的精確度也就越高。
把上面介紹的整合到一起,就能得到在我們的問(wèn)題中所需進(jìn)行的最基本的MCMC步驟:
為logistic函數(shù)的系數(shù)alpha 和beta選擇初始值?;诋?dāng)前狀態(tài)值隨機(jī)分配給alpha 和beta新的值。檢查新的隨機(jī)值是否與觀察數(shù)據(jù)吻合。如果不是,舍棄掉這個(gè)值,并回到上一狀態(tài)值。如果吻合,接受這個(gè)新的值作為當(dāng)前狀態(tài)值。重復(fù)步驟2和3(重復(fù)次數(shù)提前設(shè)置好)。這個(gè)算法會(huì)給出所有它所生成的alpha 和beta值。我們可以用這些值的平均數(shù)作為alpha 和beta在logistic函數(shù)中可能性最大的終值。MCMC不會(huì)返回“真實(shí)”的數(shù)值,而是函數(shù)分布的近似值。睡眠狀態(tài)概率分布的最終模型將會(huì)是以alph和beta均值作為系數(shù)的logistic函數(shù)。
Python實(shí)施
我再三思考模擬上面提到的細(xì)節(jié),最終我開(kāi)始用Python將它們變成現(xiàn)實(shí)。觀察一手的結(jié)果會(huì)比閱讀別人的經(jīng)驗(yàn)貼有幫助得多。想要在Python中實(shí)施MCMC,我們需要用到PyMC3貝葉斯庫(kù),它省略了很多細(xì)節(jié),方便我們創(chuàng)建模型,避免迷失在理論之中。
通過(guò)下面的這些代碼可以創(chuàng)建完整的模型,其中包含了參數(shù)alpha 、beta、概率p以及觀測(cè)值observed,step變量是指特定的算法,sleep_trace包含了模型創(chuàng)建的所有參數(shù)值。
with pm.Model() as sleep_model:# Create the alpha and beta parameters # Assume a normal distribution alpha = pm.Normal('alpha', mu=0.0, tau=0.05, testval=0.0) beta = pm.Normal('beta', mu=0.0, tau=0.05, testval=0.0) # The sleep probability is modeled as a logistic function p = pm.Deterministic('p', 1. / (1. + tt.exp(beta * time + alpha))) # Create the bernoulli parameter which uses observed data to inform the algorithm observed = pm.Bernoulli('obs', p, observed=sleep_obs) # Using Metropolis Hastings Sampling step = pm.Metropolis() # Draw the specified number of samples sleep_trace = pm.sample(N_SAMPLES, step=step);
為了更直觀地展現(xiàn)代碼運(yùn)行的效果,我們可以看一下模型運(yùn)行時(shí)alpha和beta生成的值。
這些圖叫做軌跡圖,可以看到每個(gè)狀態(tài)都與其歷史狀態(tài)相關(guān),即馬爾可夫鏈;同時(shí)每個(gè)值劇烈波動(dòng),即蒙特卡洛抽樣。
使用MCMC時(shí),常常需要放棄軌跡圖中90%的值。這個(gè)算法并不能立即展現(xiàn)真實(shí)的分布情況,最初生成的值往往是不準(zhǔn)確的。隨著算法的運(yùn)行,后產(chǎn)生的參數(shù)值才是我們真正需要用來(lái)建模的值。我使用了一萬(wàn)個(gè)樣本,放棄了前50%的值,但真正在行業(yè)中應(yīng)用時(shí),樣本量可達(dá)成千上萬(wàn)個(gè)、甚至上百萬(wàn)個(gè)。
通過(guò)足夠多的迭代,MCMC逐漸趨近于真實(shí)的值,但是估算收斂性并不容易。這篇文章中并不會(huì)涉及到具體的估算方法(方法之一就是計(jì)算軌跡的自我相關(guān)性),但是這是得到最準(zhǔn)確結(jié)果的必要條件。PyMC3的函數(shù)能夠評(píng)估模型的質(zhì)量,包括對(duì)軌跡、自相關(guān)圖的評(píng)估。
pm.traceplot(sleep_trace, ['alpha', 'beta'])pm.autocorrplot(sleep_trace, ['alpha', 'beta'])
軌跡圖(左)和自相關(guān)性圖(右)
睡眠模型
建模、模型運(yùn)行完成后,該最終結(jié)果上場(chǎng)了。我們將使用最終的5000個(gè)alpha和beta值作為參數(shù)的可能值,最終創(chuàng)建了一個(gè)單曲線來(lái)展現(xiàn)事后睡眠概率:
基于5000個(gè)樣本的睡眠概率分布
這個(gè)模型能夠很好的代表樣本數(shù)據(jù),并且展現(xiàn)了我睡眠模式的內(nèi)在變異性。這個(gè)模型給出的答案并不是簡(jiǎn)單的“是”或“否”,而是給我們一個(gè)概率。舉個(gè)例子,我們可以通過(guò)這個(gè)模型找出我在特定時(shí)間點(diǎn)睡覺(jué)的概率,或是找出我睡覺(jué)概率超過(guò)50%的時(shí)間點(diǎn):
9:30 PM probability of being asleep: 4.80%.10:00 PM probability of being asleep: 27.44%.10:30 PM probability of being asleep: 73.91%.The probability of sleep increases to above 50% at 10:14 PM.
雖然我希望在晚上10點(diǎn)入睡,但很明顯大多時(shí)候并不是這樣。我們可以看到,平均來(lái)看,我的就寢時(shí)刻是在晚上10:14。
這些值是基于樣本數(shù)據(jù)的最有可能值,但這些概率值都有一定的不確定性,因?yàn)槟P捅旧砭褪墙频?。為了展現(xiàn)這種不確定性,我們可以使用所有的alpha、beta值來(lái)估計(jì)某個(gè)時(shí)間點(diǎn)的睡覺(jué)概率,而不是使用平均值,并且把這些概率值展現(xiàn)在圖中。
晚上10:00睡覺(jué)的概率分布
這些結(jié)果能夠更好地展現(xiàn)MCMC模型真正在做的事情,即它并不是在尋找單一的答案,而是一系列可能值。貝葉斯推論在現(xiàn)實(shí)世界中非常有用,因?yàn)樗菍?duì)概率進(jìn)行了預(yù)測(cè)。我們可以說(shuō)存在一個(gè)最可能的答案,但其實(shí)更準(zhǔn)確的回復(fù)應(yīng)當(dāng)是:每個(gè)預(yù)測(cè)都有一系列的可能值。
起床模型
同樣我可以用我的起床數(shù)據(jù)創(chuàng)建類(lèi)似的模型。我希望能夠在鬧鐘的幫助下總能在早上6:00起床,但實(shí)際上并不如此。下面這張圖展現(xiàn)了基于觀測(cè)值我起床的最終模型:
基于5000個(gè)樣本的起床事后概率
可以通過(guò)模型得出我在某個(gè)特定時(shí)間起床的概率,以及我最有可能起床的時(shí)間:
Probability of being awake at 5:30 AM: 14.10%. Probability of being awake at 6:00 AM: 37.94%. Probability of being awake at 6:30 AM: 69.49%.The probability of being awake passes 50% at 6:11 AM.
看來(lái)我需要一個(gè)更生猛的鬧鐘了….
睡眠的時(shí)間
出于好奇以及實(shí)踐需求,最后我想創(chuàng)建的模型是我的睡眠時(shí)間模型。首先,我們需要尋找到一個(gè)描述數(shù)據(jù)分布的函數(shù)。事先,我認(rèn)為應(yīng)該是正態(tài)函數(shù),但無(wú)論如何我們需要用數(shù)據(jù)來(lái)證明。
睡眠時(shí)間長(zhǎng)短分布
正態(tài)分布的確能夠解釋大部分?jǐn)?shù)據(jù),但是圖中右側(cè)的異常值卻無(wú)法得到解釋(當(dāng)我睡懶覺(jué)的時(shí)候)。我們可以用兩個(gè)單獨(dú)的正態(tài)分布來(lái)代表兩種模式,但我要用偏態(tài)分布。偏態(tài)分布有三個(gè)參數(shù):平均值、偏離值,以及alpha傾斜值。這三個(gè)參數(shù)的值都需要從MCMC算法中得到。下面的代碼創(chuàng)建了模型,并且使用了Metropolis Hastings抽樣。
with pm.Model() as duration_model:# Three parameters to sample alpha_skew = pm.Normal('alpha_skew', mu=0, tau=0.5, testval=3.0) mu_ = pm.Normal('mu', mu=0, tau=0.5, testval=7.4) tau_ = pm.Normal('tau', mu=0, tau=0.5, testval=1.0) # Duration is a deterministic variable duration_ = pm.SkewNormal('duration', alpha = alpha_skew, mu = mu_, ...
學(xué)Python要學(xué)那些東西,可以往什么方向發(fā)展 行業(yè)視頻課程
學(xué)習(xí)Python的這幾天來(lái),覺(jué)得Python還是比較簡(jiǎn)單,容易上手的,就基本語(yǔ)法而言,但是有些高級(jí)特性掌握起來(lái)還是有些難度,需要時(shí)間去消化。Python給我最大的印象就是簡(jiǎn)潔,這也正是我為什么要從Java轉(zhuǎn)行Python的原因之一。
一、Python簡(jiǎn)介
ython實(shí)現(xiàn)強(qiáng)勢(shì)逆襲,而且我相信,隨著時(shí)間的推移,國(guó)內(nèi)Python語(yǔ)言未來(lái)前景也是一片向好。
Python的特點(diǎn)是優(yōu)雅簡(jiǎn)單,易學(xué)易用(雖然我感覺(jué)還是有一些概念不容易理解),Python的哲學(xué)是盡量用最少的,最簡(jiǎn)單易懂的代碼實(shí)現(xiàn)需要的功能。Python適宜于開(kāi)發(fā)網(wǎng)絡(luò)應(yīng)用,腳本寫(xiě)作,日常簡(jiǎn)單小工具等等。Python的缺點(diǎn)是效率較低,但是在大量的場(chǎng)合效率卻不是那么重要或者說(shuō)Python不是其性能瓶頸,所以不要太在意。其次是2.x-3.x的過(guò)渡使得許多3.x還缺少很多2.x下的模塊,不過(guò)也在完善中。其次就是源代碼無(wú)法加密,發(fā)布Python程序其實(shí)就是發(fā)布源代碼。
tiobe編程語(yǔ)言排行榜
一,函數(shù)
1.函數(shù)是對(duì)象,函數(shù)名即是指向?qū)?yīng)函數(shù)對(duì)象的引用,所以可以將函數(shù)名賦給一個(gè)變量,相當(dāng)于給函數(shù)起一個(gè)‘別名’。
2.Python函數(shù)可以返回”多個(gè)值“,之所以打引號(hào),是因?yàn)閷?shí)際上返回的多個(gè)值拼成了一個(gè)元組,返回這個(gè)元組。
3.定義默認(rèn)參數(shù)需要牢記:默認(rèn)參數(shù)必須指向不變對(duì)象。否則第一次調(diào)用和第二次調(diào)用結(jié)果會(huì)不一樣,因?yàn)榭勺兊哪J(rèn)參數(shù)調(diào)用后改變了。
4.可變參數(shù):傳入的參數(shù)個(gè)數(shù)是可變的,可以是0個(gè)或多個(gè)??勺儏?shù)會(huì)將你傳入的參數(shù)自動(dòng)組裝為一個(gè)tuple。在你傳入的list或tuple名字前加一個(gè) * 即說(shuō)明傳入的是可變參數(shù)。習(xí)慣寫(xiě)法為*args。
5.關(guān)鍵字參數(shù):傳入0個(gè)或多個(gè)含參數(shù)名的參數(shù),這些參數(shù)被自動(dòng)組裝成一個(gè)dict。習(xí)慣寫(xiě)法**kw,如**a表示把a(bǔ)中所有的鍵值對(duì)以關(guān)鍵字參數(shù)的形式傳入kw,獲得一個(gè)dict,這個(gè)dict是a的一份拷貝,對(duì)kw改動(dòng)不會(huì)傳遞到a
6.命名關(guān)鍵字在函數(shù)定義中跟在一個(gè)*分割符后c,d為命名關(guān)鍵字參數(shù),可以限制調(diào)用者可以傳入的參數(shù)名,同時(shí)可以提供默認(rèn)值
7.參數(shù)定義順序:必選參數(shù),默認(rèn)參數(shù),可變參數(shù)/命名關(guān)鍵字參數(shù),關(guān)鍵字參數(shù)。
8.切片操作格式為lis[首下標(biāo):尾下標(biāo):間隔],如果都不填,即lis[::]則代表整個(gè)容器lis
9.用圓括號(hào)()括起來(lái)一個(gè)列表生成式創(chuàng)建一個(gè)生成器generator,generator保存生成算法,我們可以用next(g)取得生成器g的下一個(gè)返回值。生成器的好處就是我們不需要提前生成所有列表元素,而是需要時(shí)再生成,這在某些情況下可以節(jié)省許多內(nèi)存。算法也可以不是列表生成式而是自定義函數(shù),只需在函數(shù)定義中包含yield關(guān)鍵字。
10.map()和reduce(): 二者都是高階函數(shù)。map()接收兩個(gè)參數(shù),一個(gè)是函數(shù),一個(gè)是Iterable序列,map將傳入的函數(shù)依次作用在序列每一個(gè)元素上,并把結(jié)果作為新的Iterator返回。reduce()類(lèi)似累積計(jì)算版的map(),把一個(gè)函數(shù)作用在一個(gè)序列上,每次接收兩個(gè)參數(shù),將結(jié)果繼續(xù)與序列的下一個(gè)元素做累積計(jì)算。
利用map和reduce編寫(xiě)一個(gè)str2float函數(shù),如把字符串'123.456'轉(zhuǎn)換成浮點(diǎn)數(shù)123.456:
11.fliter()函數(shù)過(guò)濾序列,類(lèi)似于map()作用于每一元素,根據(jù)返回值是True或者False決定舍棄還是保留該元素。函數(shù)返回一個(gè)Iterator。
12.sorted()函數(shù)可實(shí)現(xiàn)排序,類(lèi)似于C++庫(kù)中的sort()函數(shù),但是比其更加簡(jiǎn)潔,語(yǔ)法為sorted(lis,key=func,reverse=T/F)
key函數(shù)可實(shí)現(xiàn)自定義的排序規(guī)則,reverse表示升序還是降序。
13.一個(gè)函數(shù)可以返回一個(gè)函數(shù),但是返回時(shí)該函數(shù)并未執(zhí)行,所以返回函數(shù)中不要引用任何可能發(fā)生變化的變量,否則會(huì)出現(xiàn)邏輯錯(cuò)誤。
14.裝飾器(decorator): 當(dāng)需要增強(qiáng)函數(shù)的功能卻不希望修改函數(shù)本身,那么可以采用裝飾器這種運(yùn)行時(shí)動(dòng)態(tài)增加功能的方式,增加的功能卸載裝飾器函數(shù)中。如在執(zhí)行前后打印'begin call'和'end call',可以這樣做:
二,基礎(chǔ)
1.如果一個(gè)字符串中有許多需要轉(zhuǎn)義的字符,而又不想寫(xiě)那么多'',那么可以用 r'...' 表示 '...'內(nèi)的內(nèi)容不轉(zhuǎn)義。
2.Python的邏輯運(yùn)算and, or, not 分別對(duì)應(yīng)C語(yǔ)言中的&&, ||, !.
3.Python的整數(shù)與浮點(diǎn)數(shù)大小都沒(méi)有范圍。
4.Python中除法有兩種: '/'除出來(lái)必是浮點(diǎn)數(shù), '//'除出來(lái)是整數(shù),即地板除。
5.Python中一切皆引用。每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù)器(內(nèi)部跟蹤變量)進(jìn)行跟蹤,引用計(jì)數(shù)值表示該對(duì)象有多少個(gè)引用,當(dāng)初次產(chǎn)生賦給變量時(shí),引用計(jì)數(shù)為1,其后沒(méi)進(jìn)行下列行為中的任意一種都會(huì)增加引用計(jì)數(shù)
6.深拷貝與淺拷貝的概念與對(duì)比,有點(diǎn)復(fù)雜,看這篇文章
7.list,tuple和dict,set
list: 為列表,是一個(gè)有序集合,類(lèi)似于數(shù)組但又比數(shù)組功能強(qiáng)大,可以隨時(shí)append,pop元素,下標(biāo)從0開(kāi)始,且下標(biāo)為加n模n制,即lis[-1] = lis[len-1],下標(biāo)范圍[-len,len-1].
tuple:為元組,類(lèi)似于list,但list為可變類(lèi)型,而tuple不可變,即沒(méi)有append,pop等函數(shù)。一個(gè)建議是為了安全起見(jiàn),能用tuple代替list盡量用tuple。如果tuple只有一個(gè)元素,要寫(xiě)成如(1,)以避免歧義。
dict:字典類(lèi)型,存放key-value鍵值對(duì),可以根據(jù)key迅速地找出value,當(dāng)然,key必須是不可變類(lèi)型
三,面向?qū)ο缶幊?/p>
1.Python實(shí)例變量可以自由地綁定任何屬性
2.為了不讓內(nèi)部屬性不被外部訪問(wèn),在屬性的名稱前加上兩個(gè)下劃線__,這樣就變成了一個(gè)私有變量(private),注意,不能直接訪問(wèn)不代表一定不能訪問(wèn),事實(shí)上,加雙下劃線后Python就會(huì)將其改名為‘_class名__name’,所以還是可以這樣來(lái)訪問(wèn)這個(gè)‘私有’變量。
3.對(duì)于靜態(tài)語(yǔ)言,如果要求傳入一個(gè)class類(lèi)型的對(duì)象,那么傳入的對(duì)象必須是class類(lèi)型或者其子類(lèi),否則將無(wú)法調(diào)用class中的方法,而Python這樣的動(dòng)態(tài)語(yǔ)言有‘鴨子類(lèi)型’一說(shuō),即不一定要傳入class類(lèi)型或其子類(lèi),而只要保證傳入的對(duì)象中有要使用的方法即可。
4.如果想要限制實(shí)例可以綁定的屬性,那么在定義class時(shí)定義一個(gè)__slots__變量即可。
5.@ property裝飾器可以使一個(gè)getter方法變成屬性,如果方法名為me,那么@me.setter裝飾器則可使一個(gè)setter方法變成屬性。這樣可以使代碼更簡(jiǎn)短,同時(shí)可對(duì)參數(shù)進(jìn)行必要的檢查。注意,__slots__限制的屬性對(duì)當(dāng)前類(lèi)實(shí)例起完全限制作用,且與子類(lèi)共同定義其__slots__,也就是說(shuō)子類(lèi)可以定義自己的__slots__,子類(lèi)實(shí)例允許定義的屬性就是自身的__slots__加上父類(lèi)的__slots__,即并集。
6.通過(guò)多重繼承,可使子類(lèi)擁有多個(gè)父類(lèi)的所有功能。
7.在類(lèi)中__call__方法可使實(shí)例對(duì)象像函數(shù)那樣直接調(diào)用,作用即是該方法定義的過(guò)程。
8.ORM(Object Relational Mapping 對(duì)象關(guān)系映射),就是把關(guān)系數(shù)據(jù)庫(kù)的一行映射為一個(gè)對(duì)象,也就是一個(gè)類(lèi)對(duì)應(yīng)一個(gè)表。ORM的實(shí)現(xiàn)需要通過(guò)metaclass元類(lèi)修改類(lèi)的定義。元類(lèi)可以改變類(lèi)創(chuàng)建時(shí)的行為。
四,IO編程
1.序列化: 把變量從內(nèi)存中變成可存儲(chǔ)或傳輸?shù)倪^(guò)程稱之為序列化。Python用pickle模塊實(shí)現(xiàn)序列化。序列化之后,就可以把序列化后的內(nèi)容存儲(chǔ)到磁盤(pán)上或者通過(guò)網(wǎng)絡(luò)進(jìn)行傳輸。pickle.dumps()將對(duì)象序列化成一個(gè)bytes,而pickle.loads()可以根據(jù)bytes反序列化出對(duì)象。
2.pickle雖好,但是它專為Python而生,所以要在不同語(yǔ)言間傳遞對(duì)象,最好還是xml或者json,而json表示格式是一個(gè)字符串,更易讀取,且比xml快,所以更加適宜于對(duì)象序列化。Python內(nèi)置了json模塊,相應(yīng)方法仍然是dumps()和loads()。
3.但是在默認(rèn)情況下,有些對(duì)象是無(wú)法序列化的,所以我們有時(shí)還需要定制轉(zhuǎn)換方法,告訴json該如何將某類(lèi)對(duì)象轉(zhuǎn)換成可序列為json格式的{}對(duì)象。如下即是一個(gè)轉(zhuǎn)換方法:
五,調(diào)試
1.Python調(diào)試方法:
(1)直接打印
(2)斷言
(3)pdb
(4)IDE
想學(xué)習(xí)從事Python工作的請(qǐng)關(guān)注小編