Python 3.x 學習筆記
阿新 • • 發佈:2018-11-14
基礎語法
- 使用縮排來組織程式碼塊
- 大小寫敏感
- 基本資料型別:空值None、布林值、整數、浮點數、字串
- 程式執行過程中,變數儲存在記憶體中
- 變數本身型別不固定 - 動態語言
- 常量通常用全大寫表示
- 1箇中文字元經過UTF-8編碼後通常會佔用3個位元組,而1個英文字元只佔用1個位元組
- encode()編碼,decode()解碼
- 列表list,有序集合,[]
- 元組tuple,類似list,(),一旦定義內容不可變
- 字典dict,無序鍵值對,{}
- Set,無序無重複元素的集合,只儲存key,以set()方法構建,引數為一個list
- 函式返回多個值其實是返回一個tuple(省略了括號)
- 函式引數型別:必選引數、預設引數、可變引數、*關鍵字引數、命名關鍵字引數
- 關鍵字引數在函式內部自動組裝成為一個dict
- 命名關鍵字引數是為了限制呼叫者可以傳入的引數名,同時可以提供預設值
- 引數組合順序:必選引數、預設引數、可變引數、命名關鍵字引數和關鍵字引數
- *args是可變引數,接收一個tuple
- **kw是關鍵字引數,接收一個dict
- 對於任意函式,都可以通過func(*args, **kw)的形式呼叫
- 如果函式中包含yield關鍵字,那麼這個函式就不再是一個普通函式,而是一個generator
- 可以直接作用於for迴圈的物件統稱為迭代物件Iterable,包括str list tuple dict set generator
- 可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器Iterator
- 可以使用iter()函式把Iterable變成Iterator
- Iterator物件表示一個數據流,一個惰性計算的序列,只有在需要時才返回下一個值
函數語言程式設計
- 函式是面向過程的程式設計的基本單元
- 函式本身可以賦值給變數,即變數可以指向函式,指向函式的變數其實就是函式名
- 把函式作為引數傳入,這樣的函式稱為高階函式,這種高度抽象的程式設計正規化稱為函數語言程式設計
- 典型高階函式:map() reduce() filter() sorted()
- map()把引數函式作用在引數list的每一個元素上,並返回一個新的Iterator
- reduce()把引數函式作用於引數list,並把返回結果參與到下一個元素的運算
- filter()過濾序列
- sorted()將key指定的函式作用於list的每一個元素上,並根據函式返回的結果進行排序
- lambda匿名函式,只能有一個表示式,返回值就是該表示式的結果
- 匿名函式可以賦值給變數,也可以作為函式返回值
- 使用list(Iterator)獲取惰性序列的所有值
- 高階函式除了可以將函式作為引數外,還可以將函式作為結果值返回
- 閉包 - 在外部函式中定義內部函式,內部函式可以引用外部函式的引數和區域性變數,
- 當外部函式將內部函式作為結果值返回時,相關引數和變數都儲存在內部函式中
- 返回函式不要引用任何迴圈變數,或者後續會發生變化的變數
- 函式也是一個物件,而且可以被賦值給變數,通過變數也能呼叫該函式
- 在函式執行期間動態增加功能的方式,稱之為裝飾器Decorator
- 裝飾器的本質是返回函式的高階函式
- 使用@functools.wraps()把原始函式的name屬性複製到裝飾器中的函式
- 偏函式functools.partial()的作用就是把一個函式的某些引數固定住,即設定預設值,然後返回一個新的函式
面向物件程式設計
- 在類中定義的函式,第一個引數永遠是例項變數self,呼叫時不用傳遞該引數
- 在類屬性前加兩個下劃線,則變成了一個私有變數,外部不可直接訪問
- 特殊變數xxx是可以直接訪問的
- 多型 - 子類中的方法覆蓋父類中的同名方法
- 常用的物件分析方法:dir() hasattr() getattr() setattr()
- 例項屬性將遮蔽掉同名的類屬性
- 定義一個類,建立一個例項後,可以給該例項繫結任意屬性和方法(僅屬於當前例項)
- 使用slots限制類例項可以新增的屬性和方法,對繼承的子類不起作用
- 內建的@property裝飾器負責把一個方法變成屬性呼叫,簡化對屬性的getter/setter操作
- Python支援多重繼承,一個子類可以同時獲得多個父類的所有功能
- 在設計類的繼承關係時,通常主線都是單一繼承下來的,然後”混入”額外的功能,稱之為MixIn
- 常用的定製類方法:str repr iter next getitem getattr call
- Enum可以把一組相關常量定義在一個列舉類中,且該類不可變,成員可以直接比較
- 動態語言,函式和類的定義,不是編譯時定義的,而是執行時動態建立的
- type()既可以返回一個物件的型別,又可以創建出新的型別
- 元類metaclass,先定義metaclass,就可以建立類,然後建立例項,即可以把類看作是metaclass建立的”例項”
- 元類的常用使用場景:ORM框架
錯誤和異常處理
- 錯誤和異常是class,捕獲一個錯誤就是捕獲到該class的一個例項
- 捕獲異常try…except(else)…finally,丟擲異常raise
- 所有錯誤和異常都繼承自BaseException
- 程式除錯:列印print(),斷言assert(),日誌logging,單步執行pdb,斷點pdb.set_trace()
- 日誌級別logging.basicConfig(level=logging.INFO) debug info warning error
- TDD Test-Driven Development 測試驅動開發
- 內建單元測試模組unittest,方法setUp、tearDown
- 文件測試doctest,不但可以用來測試,還可以直接作為示例程式碼 ”’ this is doctest ”’
網路程式設計
- 網路通訊本質是兩臺計算機上的兩個程序之間的通訊
- TCP協議是建立在IP協議之上的,更高階的協議(HTTP協議、SMTP協議等)是建立在TCP協議之上的
- 小於1024的是Internet標準服務的埠,大於1024的可以任意使用
- 基於TCP協議進行Socket程式設計,客戶端要主動連線伺服器的IP和指定埠
- 對於伺服器,要首先監聽指定埠,然後對每一個新的連線,建立一個執行緒或程序來處理,通常伺服器會無限執行下去
- 使用者資料報協議UDP(User Datagram Protocol),是面向無連線的協議
- 與TCP相比,UDP不需要連線,速度更快,但資料傳輸的可靠性較差,不能保證資料一定傳送成功
- 伺服器繫結TCP埠和UDP埠互不衝突,也就是說,TCP的9999埠與UDP的9999埠可以各自繫結
電子郵件
- 電子郵件基本路徑:發件人 -> MUA -> MTA -> MTA -> 若干個MTA -> MDA <- MUA <- 收件人
- MUA: Mail User Agent 郵件使用者代理,如Foxmail
- MTA: Mail Transfer Agent 郵件傳輸代理,如網易163
- MDA: Mail Delivery Agent 郵件投遞代理
- MUA和MTA使用的協議SMTP: Simple Mail Transfer Protocol
- MUA和MDA使用的協議POP: Post Office Protocol和IMAP: Internet Message Access Protocol
- Python內建對SMTP的支援,模組email負責構造郵件,smtplib負責傳送郵件,可以傳送純文字、HTML郵件及帶附件的郵件
- poplib用來接收郵件,email用來解析郵件
資料庫操作
- SQLite是一種嵌入式資料庫,它的資料庫就是一個檔案
- SQLite由C語言寫成,體積很小,所以經常被整合到各種應用程式中,甚至移動APP中
- Python內建了SQLite及相關驅動
- 操作資料庫的基本步驟:建立連線 -> 獲取遊標 -> 執行SQL -> 關閉遊標 -> 提交事務(非查詢操作) -> 關閉連線
- 使用遊標Cursor物件執行insert update delete語句時,執行結果由rowcount返回影響的行數
- 使用遊標Cursor物件執行select語句時,通過fetchall()可以獲取結果集
- 結果集是一個list,每個元素都是一個tuple,對應一行記錄
- Python的DB-API定義對不同的資料庫是通用的
- 執行INSERT等操作後要呼叫commit()提交事務
- MySQL的SQL佔位符是%s
- ORM(Object-Relational Mapping)物件關係對映
- ORM就是把資料庫表的行與相應的物件建立關聯,把對錶的操作轉換為對物件的操作
- 常用ORM框架:SQLAlchemy
Web開發
- Web開發階段:靜態HTML -> CGI -> PHP/ASP/JSP -> MVC -> MVVM
- CGI: Common Gateway Interface, 由C/C++編寫
- HTTP 1.1版本允許多個HTTP請求複用一個TCP連線,以加快傳輸速度
- 一個HTTP請求只處理一個資源
- HTTP響應的資料格式由Content-Type決定的
- Content-Encoding: gzip是指以gzip方式對Body資料進行壓縮
- Apache Nginx Lighttpd是靜態伺服器
- Python是解釋性的指令碼語言,適合Web開發,有上百種Web開發框架
- WSGI: Web Service Gateway Interface
- Python內建了一個WSGI伺服器,這個模組叫wsgiref,它是用純Python編寫的WSGI伺服器的參考實現
- Flask通過Python的裝飾器在內部自動地把URL和函式給關聯起來,預設支援模板jinja2
- 常用Web開發框架:Flask Django web.py Bottle Tornado
- 常用模板:jinja2 Mako Cheetah Django
IO程式設計
- 流Stream, Input Stream是資料從磁碟、網路流入記憶體,Output Stream是從記憶體流出
- 同步IO和非同步IO的主要區別在於是否等待IO執行的結果
- 非同步IO的執行效率更高,但程式設計模型也更復雜
- 讀寫檔案是最常見的IO操作,該功能是呼叫作業系統提供的介面實現的
- 作業系統在同一時間能開啟的檔案數量是有限的
- 使用with語句操作檔案IO,可以確保檔案被關閉
- 開啟檔案open(‘file’, ‘r/w’, encoding=’utf-8’, errors=’ignore’) -> 讀read()/寫write() -> 關閉檔案close()
- StringIO和BytesIO是在記憶體中操作str和bytes的方法,使得和讀寫檔案具有一致的介面,getvalue()
- os模組封裝了作業系統的目錄和檔案操作,要注意這些函式有的在os模組中,有的在os.path和shutil模組中
- 把變數從記憶體中變成可儲存或傳輸的過程稱作序列化pickling, 反序列化unpickling
- 通過pickle json模組來實現序列化,dumps() loads()
程序和執行緒
- 單核CPU以時間片輪轉的方式來執行多工,真正的並行執行多工需要在多核CPU上實現
- 一個程序Process至少有一個執行緒Thread,執行緒是最小的執行單元
- 多工實現:多程序模式 多執行緒模式 多程序+多執行緒模式
- 排程程序和執行緒,完全由作業系統決定,程式自己不能決定什麼時候執行,執行多長時間
- 在Unix/Linux下,可以使用os.fork()呼叫實現多程序,跨平臺可以使用multiprocessing模組
- 使用程序池的方式批量建立子程序
- 程序間通訊通過Queue Pipes等實現
- 任何程序預設都會啟動一個執行緒,稱為主執行緒MainThread,主執行緒又可以啟動新的執行緒
- 在多程序中,同一個變數在每個程序中有一份拷貝,互不影響;在多執行緒中,變數線上程間共享
- 使用執行緒鎖threading.Lock()來對執行緒進行隔離,避免衝突
- Python程序有各自獨立的GIL鎖,互不影響,因此可以使用多程序來實現多核任務,但無法使用多執行緒來實現
- ThreadLocal變數雖然是全域性變數,但每個執行緒都只能讀寫自己執行緒的獨立副本,互不干擾
- 採用多工需要考慮的因素:任務數量(執行緒切換)和任務型別(計算密集型 vs IO密集型)
非同步IO
- 程序更穩定,而且可以分佈到多臺機器上,而執行緒最多隻能分佈在同一臺機器的多個CPU上
- 使用QueueManager模組實現分散式程序
- Nginx是支援非同步IO的Web伺服器,使用單程序單執行緒模型來執行多工,稱為事件驅動模型
- 在Python中,單執行緒的非同步程式設計模型稱為協程Coroutine
- 使用asyncio模組來實現非同步IO
- asyncio實現了TCP UDP SSL等協議,aiohttp是基於asyncio實現的HTTP框架
其他
- 正則模組re.match()返回match物件或None
- Python支援多種圖形介面的第三方庫:Tk wxWidgets Qt GTK,內建支援Tk的Tkinter