2.Python基礎
- 2020 年 1 月 10 日
- 筆記
一.語句和語法
一.繼續 ()
- Python語句,一般使用換行分隔,也就是說一行一個語句, 一行過場的語句可以使用反斜杠"" 分解成幾行.
- 兩種情況列外一個語句不使用反斜杠也可以跨行. 在使用閉合操作符時,單一語句可以哭啊多行. 例如: 在含有小括弧,中括弧,花括弧時可以多行書寫 . 另外就是三引號包括下的字元串也可以跨行書寫 .
- 如果要在使用反斜杠換行和使用括弧元素換行做一個選擇,推薦使用小括弧. 這樣可讀性會更好.
二.多個語句構成程式碼組 (:)
- 縮進相同的一組語句構成一個程式碼塊,我們稱之為程式碼組. 像if ,while,wdef 和class這樣的符合語句,首航以關鍵字開始,以 冒號(:)結束,該行之後的一行或者多行程式碼構成程式碼組.我們將首航及後面的程式碼組稱為一個子句(clause) .
三 . 程式碼組由不同的縮進分隔
- 同一程式碼組的程式碼必須嚴格左對齊.
- 核心風格 : 縮進四個空格寬度,避免使用製表符.
- 隨著縮進深度的增加,程式碼塊的層次也在加深,沒有縮進的程式碼塊是最高層次的,被稱作腳本的main 部分 .
四.同一行書寫多個語句 (;)
- 分號(;) 允許你將多個語句卸載同一行上,語句之間用分號隔開, 而這些語句也不能再這行開始一個新的程式碼塊.
五.模組
- 每一個Python腳本文件都可以當成是一個模組.模組以磁碟文件的形式存在. 當一個模組變得過大,並且驅動了太多功能的話,就應該考慮拆一些程式碼出來另外建一個模組.模組里的程式碼可以是一段直接執行的腳本,也可以是一堆類似庫函數的程式碼,從而可以被別的模組導入(import) 調用 . 模組可以包含直接運行的程式碼塊,類定義,函數定義或這幾者的組合.
二.變數賦值
注意:賦值並不是直接將一個值賦給一個變數,儘管你可能根據其他語言編程經驗認為應該如此. 在Python中,對象是通過引用傳遞的. 在賦值時,不管這個對象是新創建的.還是一個已經存在的,都是將該對象的引用(並不是值) 賦值給變數.
- 賦值運算符 : += , -=, *= , /= , %= , **= ,<<= ,>>= ,&= ,^= , /=
- 增量賦值 : 增量賦值相對普通賦值不僅僅是寫法上的改變,最有意義的變化是第一對象僅被處理一次.可變對象會被就地修改(無修改拷貝引用) , 不可變對象則和 A = A+ B結果一樣(分配一個新對象) .
- 多重賦值 : x = y = z = 1 . 這個例子中, 一個值為1的整數對象被創建,該對象的同一個引用被賦值給x,y和z . 也就是將一個對象賦給了多個變數. 當然, 在Python當中,將多個對象賦給多個變數也是可以的.
- "多元"賦值 : 另一種將多個變數同時賦值的方法我們稱為多元賦值(multuple) . 這不是官方Python術語,而是我們將"mul-tuple" 連在一起自造的. 因為採用這種方式賦值時,等號兩邊的對象都是元組 . x, y, z = 1,2,'good' . 通常元組需要用小括弧括起來,儘管他們是可選的. 我們建議總是加上小括弧,以使得你的程式碼有更高的可讀性.
三.標識符
標識符是電腦語言中允許作為名字的有效字元串集合 . 其中,有一部分是關鍵字,構成語言的標識符. 這樣的標識符是不能坐它用的標識符的,否則會引起語法錯誤.
- 合法的Python標識符 : 第一個字元必須是字母或下劃線 , 剩下的字元可以是字母和數字或下劃線,大小寫敏感.
- 關鍵字 : import keyword , keyword.iskeyword() 檢測是否為關鍵字 .
- 內建 : 除了關鍵字外,Python還有可以在任何一級程式碼使用的"內建" 名字集合,這些名字可以由解釋器設置或使用.
- 專用下劃線標識符 : Python用下劃線作為變數前綴和後綴指定特殊變數. a. _xxx , 不用from module import * 導入 b. xxx 系統定義名字 c. __xxx 類中的私有變數名
- 核心風格 : 避免用下劃線作為變數名的開始 : 因為下劃線對解釋器有特殊的意義,而且是內建標識符所使用的符號,我們建議程式設計師避免用下劃線作為變數名的開始. 一般來講,變數名_xxx 被看做是"私有的" , 在模組或類外不可以使用 . 當變數是私有的時候,用_xxx來表示變數是很好的習慣. 因為變數名xxx對Python來說有特殊含義,對於普通的變數應當避免這種命名風格 .
四. 基本風格指南
- 注釋 : 注釋對於自己和後來人來說都是非常重要的,特別是對哪些很舊沒有被動過的程式碼而言.記住,確保注釋的準確性.
- 文檔 : Python還提供一個機制,可以通過doc特別變數,動態獲得文檔字串.在模組,類聲明,或函數聲明中第一個沒有複製的字元串可以用屬性 obj.doc來進行訪問, 其中obj是一個模組,類,或函數的名字,這在運行時刻也可以運行.
五.模組結構和布局
- 用模組來合理組織你的Python程式碼是簡單又自然的方法.你應該建立一種統一且容易閱讀的結構,並將它應用到每一個文件中去. 下面就是一種非常合理的布局:
- 起始行
- 模組文檔
- 模組導入
- 變數定義
- 類定義
- 函數定義
- 主程式
- 起始行 : 有起始行就能夠僅輸入腳本名字來執行腳本,無序之界調用解釋器.
- 模組文檔 : 簡要介紹模組的功能及重要全局變數的含義,模組外可通過module.doc訪問這些內容.
- 變數定義 : 這裡定義變數為全局變數,本模組中的所有函數都可直接使用. 從好的編程風格角度說,除非必須,否則就要盡量使用局部變數代替全局變數.
- 類定義語 : 所有的類都需要在這裡定義.當模組被導入時,class語句被執行,類也就會被定義. 類的文檔變數是class.doc.
- 函數定義語句 : 此處定義的函數可以通過module.function()在外部被訪問到,當模組被導入時def 語句會被執行,函數也就都會定義好,函數的文檔變數是function.doc
- 主程式 : 無論這個模組是被別的模組導入還是作為腳本直接執行,都會執行這部分程式碼. 通常這裡不會有太多功能性程式碼,而是根據執行的模式調用不同的函數.
- 推薦程式碼風格 : 主程式調用man()函數 . 主程式程式碼通常都和你前面看到的程式碼相似,檢查name變數的值然後再執行相應的調用 . 主程式中的程式碼通常包括變數賦值,類定義和函數定義,隨後檢查name來決定是否調用另一個函數(通常調用main())函數來完成該模組的功能. 主程式通常都是做這些事. 不管用什麼名字,想強調一點那就是: 這兒是放置測試程式碼的好地方. 大部分Python模組都是用於導入調用的,直接運行模組應該調用該模組的回歸測試程式碼 . 請記住, 絕大部分的模組創建的目的是為了別人調用而不是作為獨立執行的腳本.
- 核心筆記 : name指示模組應如何被載入 : 由於主程式程式碼無論模組是被導入還是被直接執行都會運行, 我們必須知道模組如何決定運行方向. 一個應用程式可能需要導入另一個應用程式的一個模組,以便重用一些有用的程式碼(否則就只能用拷貝粘貼那種非面向對象的愚蠢手段) . 這種情況下,你只想訪問哪些位於其它應用程式中的程式碼,而不是想運行那個應用程式. 因此一個問題出現了 . Python是否有一種方法能在運行時檢測該模組是被導入還是被直接執行呢?
- 如果模組是被導入,name的值為模組名字 .
- 如果模組是被直接執行,name的值為 "main"
- 在主程式中書寫測試程式碼 : 測試程式碼僅當該文件被直接執行時運行,也就是說不是被別的模組導入時 . 我們應該利用name變數這個有利條件. 將測試程式碼放在一個或者叫main() 的函數中.如果鈣蜜快是被當成腳本運行,就調用這個函數 .這些測試程式碼應該隨著測試條件及測試結果的變更及時修改,每次程式碼更新都應該運行這些測試程式碼,以確認修改沒有引發新問題. 這要堅持這樣做,你的程式碼就會足夠簡裝,更不用提驗證和測試新特性和更新了. 在主程式中防止測試程式碼是測試程式碼塊的簡單快捷手段. Python標準庫中還提供了unittest模組,有時候它被稱為pyunit,是一個測試框架.
六.記憶體管理
- 動態類型 : Python中不但變數名無需事先聲明,而且也無需類型聲明. Python語言中,對象的類型和記憶體佔用都是運行時確定的.儘管程式碼被編譯成位元組碼,Python仍然是一種解釋型語言. 在創建–也就是賦值時,解釋器會更具語法和右側的操作數來決定新對象的類型. 在對象創建後,一個該對象的用用會被賦值給左側的變數.
- 記憶體分配 : 作為一個負責人的程式設計師,我們知道在為變數分配記憶體時,是在借用系統資源 , 在用完之後,應該釋放借用的系統資源.Python解釋器承擔了記憶體管理的複雜任務,這大大簡化了應用程式的編寫. 你只需要關心你要解決的問題,至於底層的事情放心交給Python解釋器去做就行了 .
- 引用計數 : 當對象被創建時,就創建了一個引用計數,當這個對象不再需要時,也就是說,這個對象的引用計數變為0時,它被垃圾回收 .(嚴格來說這不是100%正確,不過現階段你可以就這麼認為) 4.增加引用計數 : 當對象被創建並(將其引用) 賦值給變數時, 該對象的引用計數就被設置為1 .當同一個對象(的引用)又被賦值給其他變數時, 或作為參數傳遞給函數,方法或類實例時,或者被賦值為一個窗口帝鄉的成員時,該對象的一個新的因運用,或者稱作別名,就被創建(則該對象的引用計數自動加1). 總之,對象的引用計數在以下情況會增加 :
- 對象被創建
- 或另外的別名被創建
- 或作為參數傳遞給函數(新的本地引用)
- 或稱為容器對象的一個元素
- 減少引用計數 : 當對象的引用被銷毀時 , 引用計數會減小. 最明顯的例子就是引用離開其作用範圍時,這種情況最經常出現在函數運行結束時,所有局部變數都被自動銷毀,對象的引用計數也就隨之減少. 對象的引用計數在以下情況會減少 :
- 一個本地引用離開了其作用範圍
- 對象的別名被顯式的銷毀
- 對象的一個別名被賦值給其他的對象
- 對象被從一個窗口對象中移除
- 窗口對象本身被銷毀
- del 語句 : del 語句會刪除對象的一個引用 . 會產生兩個結果 :
- 從現在的名字空間中刪除 y.
- x 的引用計數減一 引申非同步,執行del會刪除該對象的最後一個引用,也就是改對象的引用計數會減為 0 , 這回導致該對象從此無法訪問或無法抵達. 從此刻起,改對象就稱為垃圾回收機制的回收對象. 注意任何追蹤或調試程式會給對象增加一個額外的引用,這會推遲該對象被回收的時間.
7.垃圾回收 : 不再被使用的記憶體會被一種稱為垃圾收集機制釋放. 垃圾收集器是一塊獨立程式碼,它用來尋找引用計數為0 的對象. 它也負責檢查哪些雖然引用計數大於0 但也應該銷毀的對象. 特定情形會導致循環引用.