1. 程式人生 > >Python 3.x 學習筆記

Python 3.x 學習筆記

基礎語法

  • 使用縮排來組織程式碼塊
  • 大小寫敏感
  • 基本資料型別:空值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