當我學完Python時我學了些什麼
學習Python的這幾天來,覺得Python還是比較簡單,容易上手的,就基本語法而言,但是有些高階特性掌握起來還是有些難度,需要時間去消化。Python給我最大的印象就是簡潔,這也正是我為什麼不太喜歡Java的原因之一。
一、Python簡介
Python是一種用來編寫應用程式的高階程式設計語言,TIOBE程式語言排行榜2015年12月的排名如下:
Python實現強勢逆襲,而且我相信,隨著時間的推移,國內Python語言未來前景也是一片向好。
Python的特點是優雅簡單,易學易用(雖然我感覺還是有一些概念不容易理解),Python的哲學是儘量用最少的,最簡單易懂的程式碼實現需要的功能。Python適宜於開發網路應用,指令碼寫作,日常簡單小工具等等。Python的缺點是效率較低,但是在大量的場合效率卻不是那麼重要或者說Python不是其效能瓶頸,所以不要太在意。其次是2.x-3.x的過渡使得許多3.x還缺少很多2.x下的模組,不過也在完善中。其次就是原始碼無法加密,釋出Python程式其實就是釋出原始碼。
二、基礎語法要點
1.如果一個字串中有許多需要轉義的字元,而又不想寫那麼多'\',那麼可以用 r'...' 表示 '...'內的內容不轉義。
2.Python可用'''...'''來表示多行內容,如:
1 2 3 4 5 6 |
|
3.Python的邏輯運算and, or, not 分別對應C語言中的&&, ||, !.
4.Python的整數與浮點數大小都沒有範圍。
5.Python中除法有兩種: '/'除出來必是浮點數, '//'除出來是整數,即地板除。
6.Python中一切皆引用。每個物件都有一個引用計數器(內部跟蹤變數)進行跟蹤,引用計數值表示該物件有多少個引用,當初次產生賦給變數時,引用計數為1,其後沒進行下列行為中的任意一種都會增加引用計數:
1 2 3 |
|
以下任意一種行為都會減少引用計數:
1 2 3 4 |
銷燬: del a
|
7.深拷貝與淺拷貝的概念與對比,有點複雜,看這篇文章
8.list,tuple和dict,set
list: 為列表,是一個有序集合,類似於陣列但又比陣列功能強大,可以隨時append,pop元素,下標從0開始,且下標為加n模n制,即lis[-1] = lis[len-1],下標範圍[-len,len-1].
tuple:為元組,類似於list,但list為可變型別,而tuple不可變,即沒有append,pop等函式。一個建議是為了安全起見,能用tuple代替list儘量用tuple。如果tuple只有一個元素,要寫成如(1,)以避免歧義。
dict:字典型別,存放key-value鍵值對,可以根據key迅速地找出value,當然,key必須是不可變型別,如下是錯誤的:
1 2 3 4 5 |
|
list與dict的優劣對比:
1 2 3 4 5 6 7 |
|
dict內部存放的順序和key放入的順序是沒有關係的
set:set與dict類似,相當於只有key沒有value的dict,每個key不同,set間有 &, | 等操作對應集合的交,並操作。
三、函式
1.函式是物件,函式名即是指向對應函式物件的引用,所以可以將函式名賦給一個變數,相當於給函式起一個‘別名’。
1 2 3 |
|
2.Python函式可以返回”多個值“,之所以打引號,是因為實際上返回的多個值拼成了一個元組,返回這個元組。
3.定義預設引數需要牢記:預設引數必須指向不變物件。否則第一次呼叫和第二次呼叫結果會不一樣,因為可變的預設引數呼叫後改變了。
4.可變引數:傳入的引數個數是可變的,可以是0個或多個。可變引數會將你傳入的引數自動組裝為一個tuple。在你傳入的list或tuple名字前加一個 * 即說明傳入的是可變引數。習慣寫法為*args。
5.關鍵字引數:傳入0個或多個含引數名的引數,這些引數被自動組裝成一個dict。習慣寫法**kw,如**a表示把a中所有的鍵值對以關鍵字引數的形式傳入kw,獲得一個dict,這個dict是a的一份拷貝,對kw改動不會傳遞到a
6.命名關鍵字在函式定義中跟在一個*分割符後,如
1 2 |
|
c,d為命名關鍵字引數,可以限制呼叫者可以傳入的引數名,同時可以提供預設值。
7.引數定義順序:必選引數,預設引數,可變引數/命名關鍵字引數,關鍵字引數。
8.切片操作格式為lis[首下標:尾下標:間隔],如果都不填,即lis[::]則代表整個容器lis
9.用圓括號()括起來一個列表生成式建立一個生成器generator,generator儲存生成演算法,我們可以用next(g)取得生成器g的下一個返回值。生成器的好處就是我們不需要提前生成所有列表元素,而是需要時再生成,這在某些情況下可以節省許多記憶體。演算法也可以不是列表生成式而是自定義函式,只需在函式定義中包含yield關鍵字。
10.map()和reduce(): 二者都是高階函式。map()接收兩個引數,一個是函式,一個是Iterable序列,map將傳入的函式依次作用在序列每一個元素上,並把結果作為新的Iterator返回。reduce()類似累積計算版的map(),把一個函式作用在一個序列上,每次接收兩個引數,將結果繼續與序列的下一個元素做累積計算。
利用map和reduce編寫一個str2float函式,如把字串'123.456'轉換成浮點數123.456:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
11.fliter()函式過濾序列,類似於map()作用於每一元素,根據返回值是True或者False決定捨棄還是保留該元素。函式返回一個Iterator。
12.sorted()函式可實現排序,類似於C++庫中的sort()函式,但是比其更加簡潔,語法為sorted(lis,key=func,reverse=T/F)
key函式可實現自定義的排序規則,reverse表示升序還是降序。
13.一個函式可以返回一個函式,但是返回時該函式並未執行,所以返回函式中不要引用任何可能發生變化的變數,否則會出現邏輯錯誤。
14.裝飾器(decorator): 當需要增強函式的功能卻不希望修改函式本身,那麼可以採用裝飾器這種執行時動態增加功能的方式,增加的功能解除安裝裝飾器函式中。如在執行前後列印'begin call'和'end call',可以這樣做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 |
|
15.偏函式: functools.partial(),作用是將一個函式的某些引數固定住,作為新函式的引數,即固定住該引數,返回一個新函式,使呼叫更簡單。
四、面向物件程式設計
1.Python例項變數可以自由地繫結任何屬性
2.為了不讓內部屬性不被外部訪問,在屬性的名稱前加上兩個下劃線__,這樣就變成了一個私有變數(private),注意,不能直接訪問不代表一定不能訪問,事實上,加雙下劃線後Python就會將其改名為‘_class名__name’,所以還是可以這樣來訪問這個‘私有’變數。
3.對於靜態語言,如果要求傳入一個class型別的物件,那麼傳入的物件必須是class型別或者其子類,否則將無法呼叫class中的方法,而Python這樣的動態語言有‘鴨子型別’一說,即不一定要傳入class型別或其子類,而只要保證傳入的物件中有要使用的方法即可。
4.如果想要限制例項可以繫結的屬性,那麼在定義class時定義一個__slots__變數即可,例如:
1 2 |
|
注意,__slots__限制的屬性對當前類例項起完全限制作用,且與子類共同定義其__slots__,也就是說子類可以定義自己的__slots__,子類例項允許定義的屬性就是自身的__slots__加上父類的__slots__,即並集。
[email protected] property裝飾器可以使一個getter方法變成屬性,如果方法名為me,那麼@me.setter裝飾器則可使一個setter方法變成屬性。這樣可以使程式碼更簡短,同時可對引數進行必要的檢查。
6.通過多重繼承,可使子類擁有多個父類的所有功能。
7.在類中__call__方法可使例項物件像函式那樣直接呼叫,作用即是該方法定義的過程。
8.ORM(Object Relational Mapping 物件關係對映),就是把關係資料庫的一行對映為一個物件,也就是一個類對應一個表。ORM的實現需要通過metaclass元類修改類的定義。元類可以改變類建立時的行為。
五、除錯
1.Python除錯方法:
(1)直接列印
(2)斷言
(3)pdb
(4)IDE
六、IO程式設計
1.序列化: 把變數從記憶體中變成可儲存或傳輸的過程稱之為序列化。Python用pickle模組實現序列化。序列化之後,就可以把序列化後的內容儲存到磁碟上或者通過網路進行傳輸。pickle.dumps()將物件序列化成一個bytes,而pickle.loads()可以根據bytes反序列化出物件。
2.pickle雖好,但是它專為Python而生,所以要在不同語言間傳遞物件,最好還是xml或者json,而json表示格式是一個字串,更易讀取,且比xml快,所以更加適宜於物件序列化。Python內建了json模組,相應方法仍然是dumps()和loads()。
3.但是在預設情況下,有些物件是無法序列化的,所以我們有時還需要定製轉換方法,告訴json該如何將某類物件轉換成可序列為json格式的{}物件。如下即是一個轉換方法:
1 2 3 4 5 6 |
|
七、程序與執行緒
1.Python用mutiprocessing模組來實現多程序。
2.如果要大量建立子程序,可以使用程序池:
1 |
|
示例如下:
1 2 3 4 5 6 7 8 |
|
要使用程序池需新建Pool物件,對Pool物件呼叫join()使等待池中所有子程序執行完畢,呼叫join()方法之前必須呼叫close(),且此後無法再新加子程序。
3.使用subprocess模組可以方便的啟動並管理一個子程序,控制其輸入輸出。
4.程序間通訊使用Queue,Pipes實現。
5.threading模組管理執行緒。threading.lock()建立執行緒鎖,防止同時訪問互斥資源造成的錯誤,示例如下:
1 2 3 4 5 6 7 |
|
6.ThreadLocal可以解決引數在一個執行緒中各個函式之間互相傳遞的問題。
7.managers模組實現分散式程序。
八、正則表示式與常用內建模組
1.re模組進行正則表示式編譯和匹配,如果該表示式需要匹配很多次,那麼最好進行編譯從而大大節省時間。
正則表示式匹配郵箱例子:
1 2 3 4 5 6 7 8 9 10 |
|
2.datetime模組進行日期和時間的處理,每一個時間對應一個timestamp,我們把1970年1月1日 00:00:00 UTC+00:00時區的時刻稱為epoch time,記為0
(1970年以前的時間timestamp為負數),當前時間就是相對於epoch time的秒數,稱為timestamp。字串和datetime也可以相互轉換,採用strptime()方法,字串轉換為datetime時需要設定一個識別格式,其中
1 |
|
分別表示年-月-日 時-分-秒。
從datetime得出月份,星期等字串用strftime()方法,其中:
1 |
|
分別表示星期, 月份 日期 時:分。
示例:
1 2 3 4 5 6 7 8 9 10 |
|
3.collections是Python內建的一個集合模組,提供了許多有用的集合類。
4.Base64是一種任意二進位制到文字字串的編碼方法,常用於在URL、Cookie、網頁中傳輸少量二進位制資料。
5.struct模組用來解決bytes和其他二進位制資料型別的轉換。
6.Python的hashlib提供了常見的雜湊演算法,如MD5,SHA1等等。hashlib實現簡單登入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
7.Python的內建模組itertools
提供了非常有用的用於操作迭代物件的函式。
8.urllib提供了一系列用於操作URL的功能。如GET,POST...
9.PIL(Python Imaging Library Python影象庫)是一個強大的影象處理標準庫,功能強大卻又簡單易用。現在的名字叫做Pillow。可以如下安裝Pillow:
1 |
|
從下面生成數字驗證碼的程式可以窺其一斑:
View Code
效果:
九、網路程式設計和電子郵件
2.SMTP是傳送郵件的協議,Python內建對SMTP的支援,可以傳送純文字郵件、HTML郵件以及帶附件的郵件。Python對SMTP支援有smtplib
和email
兩個模組,email
負責構造郵件,smtplib
負責傳送郵件。Python內建一個poplib
模組,實現了POP3協議,可以直接用來收郵件。由於現在絕大多數大型郵件服務商都採取了反垃圾郵件措施,所以這部分的簡單實驗並沒有成功,還需進一步研究,等遇到具體情況再說。
3.Python內嵌了sqlite資料庫,還可以自行安裝連線mysql,MySQL是當前最流行的開源資料庫,在行業內有著廣泛的應用。
十、Web開發和非同步IO
1.WSGI(Web Server Gateway Interface) 伺服器閘道器介面。
2.Python web 開發框架:
-Flask:流行的Web框架
-Django:全能型Web框架
-web.py:一個小巧的Web框架
-Bottle:和Flask類似的Web框架
-Tornado:Facebook的開源非同步Web框架
3.協程
參考讀物
1.廖雪峰Python教程【見友情連結】