既然是毫無基礎(chǔ),那就簡單介紹一下吧,python的入門其實(shí)只需要掌握幾個(gè)關(guān)鍵點(diǎn)就行,新手要先學(xué)會(huì)安裝環(huán)境、了解數(shù)據(jù)結(jié)構(gòu)、函數(shù)這些東西,再配合實(shí)操進(jìn)行實(shí)踐,基本就可以入門了。
提示!!文章內(nèi)容較長,大約需要半個(gè)小時(shí),可以先收藏再慢慢看,目錄如下:
一、了解環(huán)境
二、了解數(shù)據(jù)結(jié)構(gòu)
三、了解基本函數(shù)
四、了解Nuypm計(jì)算包
——————正文警告!!——————
一、環(huán)境Python的編寫環(huán)境,用Anaconda足矣。Anaconda是專業(yè)的數(shù)據(jù)科學(xué)計(jì)算環(huán)境,已經(jīng)集成絕大部分包和工具,不需要多余的安裝和調(diào)試。
Python版本建議3.0以上,不要選擇2.7的版本,否則你會(huì)被無盡的中文編碼問題困擾。
Anaconda在官網(wǎng)下載,選擇最新版本,約400MB。
完成安裝后,Win版本會(huì)多出幾個(gè)程序,Mac版本只有一個(gè)Navigator導(dǎo)航。數(shù)據(jù)分析最常用的程序叫Jupyter,以前被稱為IPython Notebook,是一個(gè)交互式的筆記本,能快速創(chuàng)建程序,支持實(shí)時(shí)代碼、可視化和Markdown語言。
點(diǎn)擊Jupyter進(jìn)入,它會(huì)自動(dòng)創(chuàng)建一個(gè)本地環(huán)境localhost。
點(diǎn)擊界面右上角的new,創(chuàng)建一個(gè)python文件。
開始你的Python
界面上部是工具欄,編輯撤回運(yùn)行等,下面是快捷操作,大家以后會(huì)熟悉的。頁面正中便是腳本執(zhí)行的地方,我們輸入自己第一行代碼吧:
(我就不用hello world)灰色框是輸入程序的地方,回車是換行,shift+回車執(zhí)行灰色區(qū)域的代碼,它的結(jié)果會(huì)直接在下面空白處出現(xiàn)。這就是Jupyter交互式的強(qiáng)大地方,將Python腳本分成片段式運(yùn)行,尤其適合數(shù)據(jù)分析的摸索調(diào)整工作。
這里的print叫函數(shù),和excel的函數(shù)同理,是程序執(zhí)行的主體,負(fù)責(zé)將輸入轉(zhuǎn)化成輸出(函數(shù)留在下一篇細(xì)講)。這里將hello qinlu這段文字輸出。新手可能會(huì)奇怪為什么要加引號(hào),這種用引號(hào)括起來的文字在程序中叫字符串。
Python是一門計(jì)算機(jī)語言,它的邏輯和自然語言不一樣,編程語言的目的是執(zhí)行任務(wù),所以它不能有歧義。為了規(guī)避各種歧義,人們創(chuàng)造了語法規(guī)則,只有正確的語法,才能被轉(zhuǎn)換成CPU執(zhí)行的機(jī)器碼。
先了解Python語法中的數(shù)據(jù)類型。計(jì)算機(jī)最開始只被用于數(shù)值運(yùn)算,后來被賦予了各種豐富的數(shù)據(jù)類型。
上面兩個(gè)是小學(xué)生都會(huì)的四則運(yùn)算,在計(jì)算機(jī)語言中可沒有那么簡單。它涉及了兩個(gè)數(shù)值類型,整數(shù)int和浮點(diǎn)數(shù)float。整數(shù)和浮點(diǎn)數(shù)在計(jì)算機(jī)內(nèi)部存儲(chǔ)的方式是不同的,我們不用知道具體原理,明確一點(diǎn),整數(shù)運(yùn)算是永遠(yuǎn)精確的,浮點(diǎn)運(yùn)算則可能有誤差。
兩種數(shù)據(jù)類型也可以互換,通過int函數(shù)和float函數(shù)。
有了數(shù)值,必然有文本,程序中叫字符串,用英文引號(hào)括起來表示。單引號(hào)和雙引號(hào)沒有區(qū)別,所以"qinlu"和'qinlu'是等價(jià)的,引號(hào)是邊界,輸出的時(shí)候不會(huì)包含它。當(dāng)字符串內(nèi)本身包含引號(hào)時(shí),也不影響使用。
需要注意的是,不論單引號(hào)還是雙引號(hào),一旦混用很容易出現(xiàn)錯(cuò)誤。因?yàn)槌绦虿⒉恢浪亲址倪吔邕€是符號(hào)。
解決方法有兩種,一種是使用三引號(hào),三引號(hào)代表整體引用,而且包含換行。第二種是引號(hào)前面加\,它是轉(zhuǎn)義字符,表示這個(gè)引號(hào)就是單純的字符。
三引號(hào)也可以用來注釋,通常是大段的文字解釋,如果一句話,我們更習(xí)慣用#,#后面的內(nèi)容均不會(huì)作為程序執(zhí)行。
時(shí)間是特殊的數(shù)值類型,它將結(jié)合datetime模塊講解。
還有兩個(gè)常見的數(shù)據(jù)類型,布爾值和空值。布爾值是邏輯判斷值,只有True和False。
布爾值在IF語句和數(shù)據(jù)清洗中經(jīng)常使用,利用其過濾。布爾值能和布爾值運(yùn)算,不過這里是and、not、or作為運(yùn)算符,Ttue and True = True,F(xiàn)alse and True = False,F(xiàn)alse and False = False,not True = False,True or False = True等。
空值是一個(gè)特殊的值,表示為None,None不等于0,0具有數(shù)學(xué)意義而None沒有,None更多表示該值缺失。
整數(shù),浮點(diǎn)數(shù),字符串,布爾值,空值就是Python常見的數(shù)據(jù)類型。Python3對中文的支持比較友好,所以大家可以用中文作為字符串試一下print。
數(shù)據(jù)類型構(gòu)成了變量的基礎(chǔ),變量可以是任意的數(shù)據(jù)類型。想要用變量,必須先賦予變量一個(gè)值,這個(gè)過程叫賦值。
我首先給a賦予了一個(gè)整數(shù)值1,然后改變它為字符串a(chǎn)bc,變量在Python中沒有固定的數(shù)值類型,這是Python最大的優(yōu)點(diǎn),所以它在數(shù)據(jù)分析中很靈活。這也是它被稱為動(dòng)態(tài)語言的原因,相對應(yīng)的叫靜態(tài)語言。
Python是大小寫敏感的語言,所以a和A是有區(qū)別的,這點(diǎn)請牢記。另外變量名盡可能使用英文,不要拼音,英文的可讀性是優(yōu)于拼音的。
變量有兩種拼寫風(fēng)格,一種叫駝峰,一種叫下劃線,以用戶ID為例。駝峰命名法為userId,以一串英文詞語user和id組成變量,第一個(gè)詞語的首字母小寫,第二個(gè)詞語開始的首字母均大寫。下劃線命名法為user_id,全部小寫,用_分割單詞。
一個(gè)變量的值可以被賦予另外一個(gè)變量,如果b變量之前有另外一個(gè)值,那么會(huì)被1覆蓋。呈從上而下的執(zhí)行關(guān)系。
初看a = a + 1好像有邏輯問題,其實(shí)這涉及到了程序執(zhí)行的先后順序,程序是先計(jì)算a+1的值得到2,然后將其賦予(覆蓋)了a。等號(hào)右邊的計(jì)算先于左邊,這是從右到左的邏輯關(guān)系。
有變量,自然有常量,常量是固定不變的量,可是在Python中沒有真正意義的常量,一切皆可變,它更多是習(xí)慣上的叫法,即一旦賦值,就不再改變了。
Python的基礎(chǔ)數(shù)學(xué)運(yùn)算符號(hào)有+,-,*,/,//,%。前面四個(gè)就是加減乘除,其中除法的結(jié)果一定是浮點(diǎn)數(shù)。后面兩個(gè)符號(hào)是除法的特殊形式,//代表除法中取整數(shù),%代表除法中取余數(shù)。
到這里,新手部分已經(jīng)講解完成。再來講講數(shù)據(jù)結(jié)構(gòu)。
二、數(shù)據(jù)結(jié)構(gòu)Python一共有三大數(shù)據(jù)結(jié)構(gòu),它是Python進(jìn)行數(shù)據(jù)分析的基礎(chǔ),分別是tuple元組,list數(shù)組以及dict字典。本文通過這三者的學(xué)習(xí),打下數(shù)據(jù)分析的基礎(chǔ)。
1、數(shù)組
數(shù)組是一個(gè)有序的集合,他用方括號(hào)表示。
num就是一個(gè)典型的數(shù)組。數(shù)組不限定其中的數(shù)據(jù)類型,可以是整數(shù)也可以是字符串,或者是混合型。
數(shù)組可以直接用特定的函數(shù),函數(shù)名和Excel相近。
sum是求和,len則是統(tǒng)計(jì)數(shù)組中的元素個(gè)數(shù)。
上述列舉的函數(shù)是數(shù)組內(nèi)整體元素的應(yīng)用,如果我只想針對單一的元素呢?比如查找,這里就要用到數(shù)組的特性,索引。索引和SQL中的索引差不多,都是用來指示數(shù)據(jù)所在位置的邏輯指針。數(shù)組的索引便是元素所在的序列位置。
注意,索引位置是從0開始算起,這是編程語言的默認(rèn)特色了。num[0]指數(shù)組的第一個(gè)元素,num[1]指數(shù)組的第二個(gè)元素。
我們用len()計(jì)算出了數(shù)組元素個(gè)數(shù)是5,那么它最后一個(gè)元素的索引是4。若是數(shù)組內(nèi)的元素特別多呢?此時(shí)查找數(shù)組最后一位的元素會(huì)有點(diǎn)麻煩。Python有一個(gè)簡易的方法,可以用負(fù)數(shù)表示,意為從最后一個(gè)數(shù)字計(jì)算索引。
這里的num[4]等價(jià)于num[-1],num[-2]則指倒數(shù)第二個(gè)的元素。
再來一個(gè)新問題,如何一次性選擇多個(gè)元素?例如篩選出數(shù)組前三個(gè)元素。在Python中,用:表示范圍。
num[0:3]篩選了前三個(gè)元素,方括號(hào)左邊是閉區(qū)間,右邊是開區(qū)間,所以這里是num[0],num[1]和num[2],并不包含num[3]。這個(gè)方法叫做切片。
上述是索引的特殊用法,[0:]表示從第0個(gè)索引開始,直到最后一個(gè)元素。[:3]表示從第一個(gè)元素開始,直到第3個(gè)索引。
負(fù)數(shù)當(dāng)然也有特殊用法。[-1:]表示從最后一個(gè)元素開始,因?yàn)樗呀?jīng)是最后一個(gè)元素了,所以只返回它本身。[:-1]表示從第一個(gè)元素開始到最后一個(gè)元素。num[-2:-1]和num[-3:-1]大同小異。
數(shù)組的增刪查
我們已經(jīng)了解數(shù)組的基本概念,不過仍舊停留在查找,它不涉及數(shù)據(jù)的變化。工作中,更多需要操縱數(shù)組,對數(shù)組的元素進(jìn)行添加,刪除,更改。
數(shù)組通過insert函數(shù)插入,函數(shù)的第一個(gè)參數(shù)表示插入的索引位置,第二個(gè)表示插入的值。
另外一種方式是append,直接在數(shù)組末尾添加上元素。它在之后講到迭代和循環(huán)時(shí)應(yīng)用較多。
如果要?jiǎng)h除特定位置的元素,用pop函數(shù)。如果函數(shù)沒有選擇數(shù)值,默認(rèn)刪除最后一個(gè)元素,如果有,則刪除數(shù)值對應(yīng)索引的元素。
更改元素不需要用到函數(shù),直接選取元素重新賦值即可。
到這里,數(shù)組增刪改查已經(jīng)講完,但這只是一維數(shù)組,一維數(shù)組之上還有多維數(shù)組。如果現(xiàn)在有一份數(shù)據(jù)是關(guān)于學(xué)生信息,一共有三個(gè)學(xué)生,要求包含學(xué)生的姓名,年齡,和性別,應(yīng)該怎么用數(shù)組表示呢?
有兩種思路,一種是用三個(gè)一維數(shù)組分別表示學(xué)生的姓名,年齡和性別。
學(xué)生屬性被拆分成多個(gè)數(shù)組,利用索引來表示其信息,這里的索引有些類似SQL的主鍵,通過索引查找到信息。但是這種方法并不直觀,實(shí)際應(yīng)用會(huì)比較麻煩,更好的方法是表示成多維數(shù)組。
所謂多維數(shù)組,是數(shù)組內(nèi)再嵌套數(shù)組,圖中表示的是一個(gè)寬度為3,高度為3的二維數(shù)組。此時(shí)student[0]返回的是數(shù)組而不是單一值。這種方法將學(xué)生信息合并在一起,比第一個(gè)案例更容易使用。
如果想選擇第一個(gè)學(xué)生的性別,應(yīng)該怎么辦呢?很簡單,后面再加一個(gè)索引即可。
現(xiàn)在嘗試快速創(chuàng)建一個(gè)多維數(shù)組。
[0]*3將快速生成3個(gè)元素值為0的數(shù)組,這是一種快捷操作,而[row]*4則將其擴(kuò)展成二維數(shù)據(jù),因?yàn)槭?,所以是3*4的結(jié)構(gòu)。
這里有一個(gè)注意點(diǎn),當(dāng)我們想更改多維數(shù)組中的某一個(gè)元素而不是數(shù)組時(shí),這種方式會(huì)錯(cuò)誤。
按照正常的想法,martix[1][0]將會(huì)改變第二個(gè)數(shù)組中的第一個(gè)值為1,但是結(jié)果是所有數(shù)組的第一個(gè)值都變成1。這是因?yàn)樵趍atrix = [row] * 4操作中,只是創(chuàng)建3個(gè)指向row的引用,可以簡單理解成四個(gè)數(shù)組是一體的。一旦其中一個(gè)改變,所有的都會(huì)變。
比較穩(wěn)妥的方式是直接定義多維數(shù)組,或者用循環(huán)間接定義。多維數(shù)組是一個(gè)挺重要的概念,它也能直接表示成矩陣,是后續(xù)很多算法和分析的基礎(chǔ)(不過在pandas中,它是另外一種形式了)。
2、元組
tuple叫做元組,它和數(shù)組非常相似,不過用圓括號(hào)表示。但是它最大的特點(diǎn)是不能修改。
當(dāng)我們想要修改時(shí)就會(huì)報(bào)錯(cuò)。
而選擇和數(shù)組沒有差異。
元組可以作為簡化版的數(shù)組,因?yàn)樗豢筛牡奶匦裕芏鄷r(shí)候可以作為常量使用,防止被篡改。這樣會(huì)更安全。
3、字典
字典dict全稱dictionary,以鍵值對key-value的形式存儲(chǔ)。所謂鍵值,就是將key作為索引存儲(chǔ)。用大括號(hào)表示。
圖中的'qinlu'是key,18是value值。key是唯一的,value可以對應(yīng)各種數(shù)據(jù)類型。key-value的原理不妨想象成查找字典,拼音是key,對應(yīng)的文字是value(當(dāng)然字典的拼音不唯一)。
字典和數(shù)組的差異在于,因?yàn)樽值湟詋ey的形式存儲(chǔ)和查找,所以它的查詢速度非常快,畢竟翻字典的時(shí)候你只要知道拼音就能快速定位了。對dict數(shù)據(jù)結(jié)構(gòu),10個(gè)key和10萬個(gè)key在查找對應(yīng)的value時(shí)速度沒有太大差別。
這種查找方式的缺點(diǎn)是占用內(nèi)存大。數(shù)組則相反,查找速度隨著元素的增加逐漸下降,這個(gè)過程想象成程序在一頁頁的翻一本沒有拼音的字典,直到找到內(nèi)容。數(shù)組的優(yōu)點(diǎn)是占用的內(nèi)存空間小。
所以數(shù)組和字典的優(yōu)缺點(diǎn)相反,dict是空間換時(shí)間,list是時(shí)間換空間,這是編程中一個(gè)比較重要的概念。實(shí)際中,數(shù)據(jù)分析師的工作不太涉及工程化,選用數(shù)組或者字典沒有太嚴(yán)苛的限制。
細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn),字典定義時(shí)我的輸入順序是qinlu,lulu,qinqin,而打印出來是lulu,qinlu,qinqin,順序變了。這是因?yàn)槎x時(shí)key的順序和放在內(nèi)存的key順序沒有關(guān)系,key-value通過hash算法互相確定,甚至不同Python版本的哈希算法也不同。這一點(diǎn)應(yīng)用中要避免出錯(cuò)。
既然字典通過key-value對匹配查找,那么它自然不能不用數(shù)組的數(shù)值索引,它只能通過key值。
如果key不存在,會(huì)報(bào)錯(cuò)。通過in方法,可以返回True或False,避免報(bào)錯(cuò)。
dict和list一樣,直接通過賦值更改value
能不能更改key的名字?不能,key一旦確定,就無法再修改,好比字典定好后,你能修改字的拼音么?
dict中刪除key和list一樣,通過pop函數(shù)。增加key則是直接賦予一個(gè)新的鍵值對。
dict的keys和values兩個(gè)函數(shù)直接輸出所有的key值和value值。如果要轉(zhuǎn)換成數(shù)組,則再外面嵌套一個(gè)list函數(shù)
items函數(shù),將key-value對變成tuple形式,以數(shù)組的方式輸出。
字典可以通過嵌套應(yīng)用更復(fù)雜的數(shù)據(jù)格式,和NoSQL與JSON差不多。
基礎(chǔ)的數(shù)據(jù)類型差不多了,更多函數(shù)應(yīng)用大家可以網(wǎng)上自行查閱文檔,這塊掌握了,在數(shù)據(jù)清洗過程中將會(huì)非常高效,尤其是讀取Excel數(shù)據(jù)時(shí)。當(dāng)然不要求滾瓜爛熟,因?yàn)楹竺鎸W(xué)習(xí)更加強(qiáng)大的Numpy和Pandas。
三、基本函數(shù)1. 函數(shù)是什么
函數(shù)(Functions)是指可重復(fù)使用的程序片段。它們允許你為某個(gè)代碼塊賦予名字,允許你通過這一特殊的名字在你的程序任何地方來運(yùn)行代碼塊,并可重復(fù)任何次數(shù)。這就是所謂的調(diào)用(Calling)函數(shù)。
在 Python 中,函數(shù)可以通過關(guān)鍵字 def 來定義。這一關(guān)鍵字后跟一個(gè)函數(shù)的標(biāo)識(shí)符名稱,再跟一對圓括號(hào),其中可以包括一些變量的名稱,再以冒號(hào)結(jié)尾,結(jié)束這一行。隨后而來的語句塊是函數(shù)的一部分。
在定義函數(shù)時(shí)給定的名稱稱作“形參”(Parameters),在調(diào)用函數(shù)時(shí)你所提供給函數(shù)的值稱作“實(shí)參”(Arguments)。
2. 調(diào)用函數(shù)
要調(diào)用一個(gè)函數(shù),需要知道函數(shù)的名稱和參數(shù)。函數(shù)的參數(shù)只是輸入到函數(shù)之中,以便我們可以傳遞不同的值給它,并獲得相應(yīng)的結(jié)果。
Python 內(nèi)置的常用函數(shù)包括數(shù)據(jù)類型轉(zhuǎn)換函數(shù),比如int()函數(shù)可以把其他數(shù)據(jù)類型轉(zhuǎn)換為整數(shù)。用input()讀取用戶的輸入:
因?yàn)閕nput()返回的數(shù)據(jù)類型是str,str不能直接和整數(shù)比較,必須先把str轉(zhuǎn)換成整數(shù)。Python 提供了int()函數(shù)來完成這件事情:
函數(shù)名其實(shí)就是指向一個(gè)函數(shù)對象的引用,完全可以把函數(shù)名賦給一個(gè)變量,相當(dāng)于給這個(gè)函數(shù)起了一個(gè)“別名”:
如果函數(shù)調(diào)用出錯(cuò),一定要學(xué)會(huì)看錯(cuò)誤信息。
3.定義函數(shù)
在 Python 中,定義一個(gè)函數(shù)要使用def語句,依次寫出函數(shù)名、括號(hào)、括號(hào)中的參數(shù)和冒號(hào):,然后,在縮進(jìn)塊中編寫函數(shù)體,函數(shù)的返回值用return語句返回。
在 Python 交互環(huán)境中定義函數(shù)時(shí),注意 Python 會(huì)出現(xiàn)...的提示。函數(shù)定義結(jié)束后需要按兩次回車重新回到>>>提示符下:
如果你已經(jīng)把my_abs()的函數(shù)定義保存為abstest.py文件了,那么,可以在該文件的當(dāng)前目錄下啟動(dòng)Python 解釋器,用from abstest import my_abs來導(dǎo)入my_abs()函數(shù),注意abstest是文件名(不含.py擴(kuò)展名)。
定義一個(gè)什么事也不做的空函數(shù),可以用pass語句:
pass語句什么都不做,實(shí)際上它可以用作為占位符,比如現(xiàn)在還沒想好怎么寫函數(shù)的代碼,就可以先放一個(gè)pass,讓代碼能運(yùn)行起來。
pass還可以用在其他語句里,比如:
缺少了pass,代碼運(yùn)行就會(huì)有語法錯(cuò)誤。
數(shù)據(jù)類型檢查可以用內(nèi)置函數(shù)isinstance()實(shí)現(xiàn)。
Python 的函數(shù)返回多值其實(shí)就是返回一個(gè)tuple;Python 函數(shù)返回的是單一值時(shí),返回值仍然是一個(gè)tuple。但是,在語法上,返回一個(gè)tuple可以省略括號(hào),而多個(gè)變量可以同時(shí)接收一個(gè)tuple,按位置賦給對應(yīng)的值。函數(shù)可以同時(shí)返回多個(gè)值,但其實(shí)就是一個(gè)tuple。
函數(shù)執(zhí)行完畢也沒有return語句時(shí),自動(dòng)return None。
4.函數(shù)的參數(shù)
Python 的函數(shù)定義非常簡單,但靈活度卻非常大。除了正常定義的必選參數(shù)外,還可以使用默認(rèn)參數(shù)、可變參數(shù)和關(guān)鍵字參數(shù),使得函數(shù)定義出來的接口,不但能處理復(fù)雜的參數(shù),還可以簡化調(diào)用者的代碼。
4.1 位置參數(shù):
power(x, n)函數(shù)有兩個(gè)參數(shù):x和n,這兩個(gè)參數(shù)都是位置參數(shù),調(diào)用函數(shù)時(shí),傳入的兩個(gè)值按照位置順序依次賦給參數(shù)x和n。
4.2 默認(rèn)參數(shù):
對于一些函數(shù)來說,你可能為希望使一些參數(shù)可選并使用默認(rèn)的值,以避免用戶不想為他們提供值的情況。默認(rèn)參數(shù)值可以有效幫助解決這一情況。你可以通過在函數(shù)定義時(shí)附加一個(gè)賦值運(yùn)算符=來為參數(shù)指定默認(rèn)參數(shù)值。要注意到,默認(rèn)參數(shù)值應(yīng)該是常數(shù)。更確切地說,默認(rèn)參數(shù)值應(yīng)該是不可變的。
n = 2 是默認(rèn)參數(shù)
定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對象。且只有那些位于參數(shù)列表末尾的參數(shù)才能被賦予默認(rèn)參數(shù)值,意即在函數(shù)的參數(shù)列表中擁有默認(rèn)參數(shù)值的參數(shù)不能位于沒有默認(rèn)參數(shù)值的參數(shù)之前。
4.3 可變參數(shù):
有時(shí)你可能想定義的函數(shù)里面能夠有任意數(shù)量的變量,也就是參數(shù)數(shù)量是可變的,這可以通過使用星號(hào)來實(shí)現(xiàn)。即傳入的參數(shù)個(gè)數(shù)是可變的。
我們聲明一個(gè)諸如 *param 的星號(hào)參數(shù)時(shí),從此處開始直到結(jié)束的所有位置參數(shù)(Positional Arguments)都將被收集并匯集成一個(gè)稱為param的元組(Tuple)。
類似地,當(dāng)我們聲明一個(gè)諸如 **param 的雙星號(hào)參數(shù)時(shí),從此處開始直至結(jié)束的所有關(guān)鍵字參數(shù)都將被收集并匯集成一個(gè)名為 param 的字典(Dictionary)。
4.4 關(guān)鍵字參數(shù):
如果你有一些具有許多參數(shù)的函數(shù),而你又希望只對其中的一些進(jìn)行指定,那么你可以通過命名它們來給這些參數(shù)賦值——這就是關(guān)鍵字參數(shù)(Keyword Arguments)——我們使用命名(關(guān)鍵字)而非位置來指定函數(shù)中的參數(shù)。
關(guān)鍵字參數(shù)允許你傳入 0 個(gè)或任意個(gè)含參數(shù)名的參數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動(dòng)組裝為一個(gè)dict。
舉個(gè)例子,擴(kuò)展函數(shù)的功能。試想你正在做一個(gè)用戶注冊的功能,除了用戶名和年齡是必填項(xiàng)外,其他都是可選項(xiàng),利用關(guān)鍵字參數(shù)來定義這個(gè)函數(shù)就能滿足注冊的需求。
和可變參數(shù)類似,也可以先組裝出一個(gè)dict,然后,把該dict轉(zhuǎn)換為關(guān)鍵字參數(shù)傳進(jìn)去:
4.5 命名關(guān)鍵字參數(shù):
如果要限制關(guān)鍵字參數(shù)的名字,就可以用命名關(guān)鍵字參數(shù),例如,只接收city和job作為關(guān)鍵字參數(shù)。這種方式定義函數(shù)并調(diào)用:
和關(guān)鍵字參數(shù)**kw不同,命名關(guān)鍵字參數(shù)需要一個(gè)特殊分隔符*,*后面的參數(shù)被視為命名關(guān)鍵字參數(shù)。
命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名,這和位置參數(shù)不同。如果沒有傳入?yún)?shù)名,調(diào)用將報(bào)錯(cuò)。
使用命名關(guān)鍵字參數(shù)時(shí),要特別注意,如果沒有可變參數(shù),就必須加一個(gè)*作為特殊分隔符。如果缺少*,Python 解釋器將無法識(shí)別位置參數(shù)和命名關(guān)鍵字參數(shù),即缺少 *,city和job被視為位置參數(shù)。
4.6 參數(shù)組合:
在 Python 中定義函數(shù),可以用必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù),這 5 種參數(shù)都可以組合使用。
但是參數(shù)定義的順序必須是:必選參數(shù)、默認(rèn)參數(shù)、可變參數(shù)、命名關(guān)鍵字參數(shù)和關(guān)鍵字參數(shù)。雖然可以組合多達(dá) 5 種參數(shù),但不要同時(shí)使用太多的組合,否則函數(shù)接口的可理解性很差。
通過一個(gè)tuple和dict,你也可以調(diào)用函數(shù):
對于任意函數(shù),都可以通過類似func(*args, **kw)的形式調(diào)用它,無論它的參數(shù)是如何定義的。
5. 遞歸函數(shù)
如果一個(gè)函數(shù)在內(nèi)部調(diào)用自身本身,這個(gè)函數(shù)就是遞歸函數(shù)。理論上,所有的遞歸函數(shù)都可以寫成循環(huán)的方式,但循環(huán)的邏輯不如遞歸清晰。
使用遞歸函數(shù)需要注意防止棧溢出。在計(jì)算機(jī)中,函數(shù)調(diào)用是通過棧(stack)這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的,每當(dāng)進(jìn)入一個(gè)函數(shù)調(diào)用,棧就會(huì)加一層棧幀,每當(dāng)函數(shù)返回,棧就會(huì)減一層棧幀。由于棧的大小不是無限的,所以,遞歸調(diào)用的次數(shù)過多,會(huì)導(dǎo)致棧溢出。
通過下面的代碼可以查看你的電腦最大算到多少:
解決遞歸調(diào)用棧溢出的方法是通過尾遞歸優(yōu)化,事實(shí)上尾遞歸和循環(huán)的效果是一樣的,所以,把循環(huán)看成是一種特殊的尾遞歸函數(shù)也是可以的。
尾遞歸是指,在函數(shù)返回的時(shí)候,調(diào)用自身本身,并且,return語句不能包含表達(dá)式。這樣,編譯器或者解釋器就可以把尾遞歸做優(yōu)化,使遞歸本身無論調(diào)用多少次,都只占用一個(gè)棧幀,不會(huì)出現(xiàn)棧溢出的情況。
要改成尾遞歸方式,需要多一點(diǎn)代碼,主要是要把每一步的乘積傳入到遞歸函數(shù)中。Python 標(biāo)準(zhǔn)的解釋器沒有針對尾遞歸做優(yōu)化,任何遞歸函數(shù)都存在棧溢出的問題
四、了解Mumpy包Python數(shù)據(jù)分析絕對繞不過的四個(gè)包是numpy、scipy、pandas還有matplotlib。
numPy是Python數(shù)值計(jì)算最重要的基礎(chǔ)包,大多數(shù)提供科學(xué)計(jì)算的包都是用numPy的數(shù)組作為構(gòu)建基礎(chǔ)。專門用來處理矩陣,它的運(yùn)算效率比列表更高效。
1、NumPy 的 ndarray:多維數(shù)組對象
numpy的數(shù)據(jù)結(jié)構(gòu)是n維的數(shù)組對象,叫做ndarray。可以用這種數(shù)組對整塊數(shù)據(jù)執(zhí)行一些數(shù)學(xué)運(yùn)算,其語法跟標(biāo)量元素之間的運(yùn)算一樣。
創(chuàng)建并操作多維數(shù)組:
"/>這里沒寫 np.float64 只寫了 float,但是NumPy會(huì)將 Python 類型映射到等價(jià)的dtype上。
數(shù)組的dtype的另一個(gè)用法:
"/>u4(unit32):無符號(hào)的 32 位(4個(gè)字節(jié))整型。
調(diào)用astype無論如何都會(huì)創(chuàng)建出一個(gè)新的數(shù)組(原始數(shù)據(jù)的一份拷貝)。
浮點(diǎn)數(shù)只能表示近似的分?jǐn)?shù)值,在復(fù)雜計(jì)算中可能會(huì)積累一些浮點(diǎn)錯(cuò)誤,因此比較操作只在一定小數(shù)位以內(nèi)有效。
4、數(shù)組和標(biāo)量之間的運(yùn)算
數(shù)組:可對數(shù)據(jù)執(zhí)行批量運(yùn)算(不用編寫循環(huán)即可)。這通常叫做矢量化(vectorization)。
大小相等的數(shù)組之間,它們之間任何的算術(shù)運(yùn)算都會(huì)應(yīng)用到元素級(jí)(每個(gè)元素都做這個(gè)運(yùn)算了),數(shù)組與標(biāo)量的算術(shù)運(yùn)算也是。不同大小的數(shù)組之間的運(yùn)算叫做廣播(broadcasting)。5、索引和切片
數(shù)據(jù)不會(huì)被復(fù)制,任何修改都直接改了原數(shù)組。
如果僅是要一份副本,則用 .copy()。
對二維數(shù)組單個(gè)元素的索引:
這兩種方式等價(jià)。
若arr2d[2],則輸出的是一維數(shù)組[7,8,9]。
2*2*3的數(shù)組(2組2行3列):
6、布爾型索引
需要先引入:from numpy.random import randn
或?qū)⒋a改成:data = np.random.randn(7, 4)
布爾型數(shù)組的長度必須跟被索引的軸長度一致。每個(gè)名字對應(yīng) data 數(shù)組一行。
對條件進(jìn)行否定的兩種方式:
組合應(yīng)用多個(gè)布爾條件,可使用&、|等布爾算術(shù)運(yùn)算符
通過布爾型索引選取數(shù)組中的數(shù)組,將總是創(chuàng)建數(shù)據(jù)的副本,即使返回一模一樣的數(shù)組也是一樣。
通過布爾型數(shù)組設(shè)置值:
通過一維布爾數(shù)組設(shè)置整行或列的值:
7、花式索引
指利用整數(shù)數(shù)組進(jìn)行索引。
np.empty((8,4))
Return a new array of given shape and type, without initializing entries.
for i in range(8):
arr[i] = i
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step
為了以特定順序選取行的子集,只需傳入一個(gè)用于指定順序的整數(shù)列表或 ndarray,使用負(fù)數(shù)索引會(huì)從末尾開始選取行(最后一行是 -1)。
一次傳入多個(gè)索引組,返回一個(gè)一維數(shù)組:
取整列的兩種方法,相當(dāng)于給列排了順序:
花式索引跟切片不一樣,總是將數(shù)據(jù)復(fù)制到新數(shù)組中。
數(shù)組轉(zhuǎn)置和軸對換
轉(zhuǎn)置返回的是源數(shù)據(jù)的視圖,不進(jìn)行任何復(fù)制操作。數(shù)組有 transpose 方法,還有一個(gè) T 屬性來完成轉(zhuǎn)置:
8、高維數(shù)組
Transpose 要一個(gè)軸編號(hào):
<img class="capture deal" src="http://s3.pstatp.com/wenda/wenda_web/static/style/image/loading_a788ad0.gif" _src="data:image/svg+xml;utf8,<svg xmlns=" http:="" www.w3.org="" 2000="" svg'="" width="640" height="462">"/>arr是 2 組 2 行 4 列的數(shù)組,transpose的參數(shù)表示shape的形狀,對于這個(gè)例子來說,即2[0]、2[1]、4[2],transpose(1,0,2)轉(zhuǎn)置后變?yōu)?[1]、2[0]、4[2],看起來仍是 2 組 2 行 4 列的形狀,但數(shù)組內(nèi)的元素經(jīng)過轉(zhuǎn)換后索引已經(jīng)改變,也要遵循(1,0,2)的順序。如轉(zhuǎn)置前的數(shù)組arr[0,1,0]索引值為 4,轉(zhuǎn)置后的數(shù)組arr'[1,0,0],索引值才為 4。其它同理。
ndarray 的 swapaxes 方法接受一對軸編號(hào)且返回源數(shù)據(jù)的視圖:
"/>np.meshgrid函數(shù)接受兩個(gè)一維數(shù)組,并產(chǎn)生兩個(gè)二維矩陣(對應(yīng)于兩個(gè)數(shù)組中所有的(x, y)對。
將條件邏輯表述為數(shù)組運(yùn)算
np.wherea函數(shù)是三元表達(dá)式x if condition else y的矢量化版本。
np.where的第二個(gè)和第三個(gè)參數(shù)不必是數(shù)組,傳遞給where的數(shù)組大小可以不相等,甚至可以是標(biāo)量值。在數(shù)據(jù)分析工作中,where通常用于根據(jù)另一個(gè)數(shù)組而產(chǎn)生一個(gè)新的數(shù)組。
用where表述出更復(fù)雜的邏輯:(where的嵌套)
"/>10、排序
多維數(shù)組可以在任何一個(gè)軸向上進(jìn)行排序,只需將軸編號(hào)傳給sort:
頂級(jí)方法np.sort返回的數(shù)組已排序的副本,就地排序則會(huì)修改數(shù)組。
唯一化以及其他的集合邏輯
np.unique找出數(shù)組中的唯一值并返回已排序的結(jié)果
np.in1d用于測試一個(gè)數(shù)組的值在另一個(gè)數(shù)組的情況。