1. 程式人生 > 實用技巧 >Python 進階

Python 進階

看了之前寫的稍微大規模一些的python程式碼,想改但是無處入手,深覺自己程式碼欠缺規範性,設計模式也沒咋好好學過

從幾個方面重新磨一下刀

1.編輯器

VSCODE: 自帶高亮,程式碼補全,自帶終端,可以在左下角調整python版本

VSCODE下啟用Python外掛: AVisual Studio Codeextensionwith rich support for thePython language(for allactively supported versionsof the language: 2.7, >=3.5), including features such as IntelliSense, linting, debugging, code navigation, code formatting, Jupyter notebook support, refactoring, variable explorer, test explorer, snippets, and more!

IntelliSense: 智慧補全,和vscode自己的補全相比,支援常見類和自定義類的內容補全。vscode的補全只是把上下文中出現過的進行補全。

debugging: 沒有Python擴充套件包,是沒有python debug環境的。

  • IntelliSense: Edit your code with auto-completion, code navigation, syntax checking and more

  • Linting: Get additional code analysis with Pylint, Flake8 and more, 程式碼檢查,函式提示,

  • Code formatting: Format your code with black, autopep or yapf,https://www.cnblogs.com/bonelee/p/11045196.html python的formatting沒什麼用

  • Debugging: Debug your Python scripts, web apps, remote or multi-threaded processes 斷點,單步除錯很友好

  • Testing: Run and debug tests through the Test Explorer with unittest, pytest or nose

  • Jupyter Notebooks: Define and run code cells, render plots, visualize variables through the variable explorer and more,要在對應環境下,安裝一次jupyter。

  • Environments: Automatically activate and switch between virtualenv, venv, pipenv, conda and pyenv environments

  • Refactoring: Restructure your Python code with variable extraction, method extraction and import sorting

其它擴充套件包,待續

轉自https://zhuanlan.zhihu.com/p/94634073

Python語言規範

  • 匯入包:使用模組全路徑來匯入包,這樣能夠避免模組名稱相同而造成的衝突
  • python 編寫一個包,https://blog.csdn.net/destinyuan/article/details/51704935
  • 異常處理:首先,raise丟擲異常丟擲異常時應該使用已有的異常類或者自定義異常類,例如,raise MyException("Error message"),避免丟擲一串不知所云的字串,例如,raise "Error message"。其次,用except捕獲異常時避免使用Exception這類泛泛的異常。以上兩點主要為了幫助後期除錯,能夠清楚丟擲的什麼型別的異常,捕獲了什麼樣的錯誤,有助於除錯。
  • 全域性變數:儘量避免使用全域性變數,可以用類變數替代。
  • 列表推導:在簡單的情況下鼓勵使用列表推導式,複雜的情況下避免使用列表推導式,難以閱讀,例如,下方,對映表示式, for語句, 過濾器表示式中簡單的情形可以用一行列表推導式代替多行程式碼。
result = []
for x in range(10):
    result.append(x * x)

result = [x ** 2 for x in range(10)]
  • 生成器:生成器可以有效的節省記憶體佔用情況,可以按需使用生成器。
  • 預設引數值:定義一個函式式,我們為了應對某些特例情況而新增幾個引數,但是大多數情況下是用不到的,我們可以採用預設引數值的方式應對這些特例呼叫問題,這裡需要注意,預設引數值不要使用可變物件,例如,列表、字典等。
  • True/False的求值:儘量的使用隱式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被認為是false,我們在獲取這些返回值時可以用隱式的false,例如,返回的foo是一個空列表,我們可以用if foo:來判斷它是否為“空”,而不是if foo==[]:,這樣不僅更加易讀,而且能夠避免犯錯。
  • 過時的語言特性:在很多程式碼裡面習慣於使用filter、map、reduce這類語言特性,儘可能使用列表推導或者for迴圈替代。

以上介紹的是Python在語言方面的規範,也就是說不用這種方式也可以同樣實現對應的功能,但是通過上述語言規範能夠更多的避免細微之處帶來的錯誤,下面就來介紹一下Python風格規範

文件字串:函式,類裡面第一個雙括號包含的字串,https://www.zhihu.com/question/263349308

最頂上的docstring介紹了我們應該怎麼使用這個函式,包括引數是什麼,返回型別是什麼,返回的值是怎樣的等等。這裡的docstring完全沒有提到這個函式是如何實現的。

python 開頭執行的#!/usr/bin/python3,選擇直譯器,選擇編碼方式,#coding:utf-8

這兩個在我現在的程式設計過程裡基本都不需要了,也是進步吧

https://www.jianshu.com/p/400c612381dd

https://www.jianshu.com/p/e57631b827d0

python 建立一個庫/模組

第一行的文件字串,對整個庫/模組而言,

'doc of a test module' #文件字串

__author__ = 'XuZhiyuan' #寫入author

https://blog.csdn.net/destinyuan/article/details/51698789

Python中第三方模組的安裝

這段沒咋看懂,這幾個模組管理工具的使用

https://blog.csdn.net/destinyuan/article/details/51698253

自定義模組的import

https://blog.csdn.net/destinyuan/article/details/45640447

模組與包

當代碼越來越多的時候,將所有的程式碼放入一個.py檔案中會顯得難以維護。解決辦法則是程式碼分拆入不同的.py檔案中,形成不同模組,這樣做還能使得同名變數互不影響,需要注意的是,模組名不應與系統內建函式重名。
同時,不同的.py檔案也可能同名,這時候就可以考慮將其放入不同的資料夾中,形成不同的,防止同名模組的影響。

在python中一個檔案可以被看成一個獨立模組,而包對應著資料夾。模組把python程式碼分成一些有組織的程式碼段,通過匯入的方式實現程式碼重用包將有聯絡的模組組織在一起,有效避免模組名稱衝突問題,讓應用組織結構更加清晰。區別包和資料夾的重要特徵就是包資料夾內每一層目錄都有初始化檔案__init__.py

__init__.py可以是空檔案,也可以有Python程式碼,因為__init__.py本身就是一個模組,而它的模組名就是包的名稱!
所以import arcpy的時候,arcpy是包的名稱,實際上匯入的是這個包資料夾下面的__init__.py檔案。

建立包並匯入

https://blog.csdn.net/destinyuan/article/details/51704935

PyTHON 語言規範

https://zhuanlan.zhihu.com/p/94634073

  • 匯入包:使用模組全路徑來匯入包,這樣能夠避免模組名稱相同而造成的衝突 #不知道啥意思
  • 異常處理:首先,raise丟擲異常丟擲異常時應該使用已有的異常類或者自定義異常類,例如,raise MyException("Error message"),避免丟擲一串不知所云的字串,例如,raise "Error message"。其次,用except捕獲異常時避免使用Exception這類泛泛的異常。以上兩點主要為了幫助後期除錯,能夠清楚丟擲的什麼型別的異常,捕獲了什麼樣的錯誤,有助於除錯。
  • 全域性變數:儘量避免使用全域性變數,可以用類變數替代。
  • 列表推導:在簡單的情況下鼓勵使用列表推導式,複雜的情況下避免使用列表推導式,難以閱讀,例如,下方,對映表示式, for語句, 過濾器表示式中簡單的情形可以用一行列表推導式代替多行程式碼。
  • 生成器:生成器可以有效的節省記憶體佔用情況,可以按需使用生成器。
  • 預設引數值:定義一個函式式,我們為了應對某些特例情況而新增幾個引數,但是大多數情況下是用不到的,我們可以採用預設引數值的方式應對這些特例呼叫問題,這裡需要注意,預設引數值不要使用可變物件,例如,列表、字典等。
  • True/False的求值:儘量的使用隱式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被認為是false,我們在獲取這些返回值時可以用隱式的false,例如,返回的foo是一個空列表,我們可以用if foo:來判斷它是否為“空”,而不是if foo==[]:,這樣不僅更加易讀,而且能夠避免犯錯。
  • 過時的語言特性:在很多程式碼裡面習慣於使用filter、map、reduce這類語言特性,儘可能使用列表推導或者for迴圈替代。

python 程式碼風格

https://zhuanlan.zhihu.com/p/149492180

1.行長度不超過80,使用括號跳行

2.括號的寧缺毋濫:不要在返回語句或條件語句中使用括號

3.縮排:空格是首選的縮排方法。製表符應僅用於與已經使用製表符縮排的程式碼保持一致.Python 3不允許混合使用製表符和空格進行縮排.

老子一直是tab,怎麼了嘛。(但是PEP8參考一下就好了,tab在許多IDE是可以轉為空格的,pycharm一直沒用過,範洪昌說是可以的

不同的系統,編輯器對於TAB的解釋是不同的,tab所佔的長度不同。但是無所謂啊,功能應該是不影響的,老子寧願用了tab最後再翻譯成空格,也不要寫的時候用四個空格。

4.空行:頂級定義之間空兩行,兩個類,兩個函式。方法定義之間空行,兩個類方法,類和第一個方法

5.空格:在二元操作符兩邊都加上一個空格, 比如賦值(=), 比較(==, <, >, !=, <>, <=, >=, in, not in, is, is not), 布林(and, or, not). 至於算術操作符兩邊的空格該如何使用, 需要你自己好好判斷. 不過兩側務必要保持一致.

6.當'='用於指示關鍵字引數或預設引數值時, 不要在其兩側使用空格.

yes:

def complex(real, imag=0.0): return magic(r=real, i=imag)

no:

def complex(real, imag = 0.0): return magic(r = real, i = imag)

7.如果一個類不繼承自其它類, 就顯式的從object繼承. 巢狀類也一樣.

繼承自 object 是為了使屬性(properties)正常工作, 並且這樣可以保護你的程式碼, 使其不受Python 3000的一個特殊的潛在不相容性影響. 這樣做也定義了一些特殊的方法, 這些方法實現了物件的預設語義, 包括 __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__, and __str__ .

感覺沒什麼差別,繼承或者不繼承自object,也都有這些屬性,無非是空的

8.避免在迴圈中用+和+=操作符來累加字串. 由於字串是不可變的, 這樣做會建立不必要的臨時物件, 並且導致二次方而不是線性的執行時間. 作為替代方案, 你可以將每個子串加入列表, 然後在迴圈結束後用 .join 連線列表. (也可以將每個子串寫入一個 cStringIO.StringIO 快取中.)

9.

匯入總應該放在檔案頂部, 位於模組註釋和文件字串之後, 模組全域性變數和常量之前. 匯入應該按照從最通用到最不通用的順序分組:

  1. 標準庫匯入
  2. 第三方庫匯入
  3. 應用程式指定匯入
使用完整路徑匯入
import foo from foo import bar from foo.bar import baz from foo.bar import Quux from Foob import ar

10.訪問控制

在Python中, 對於瑣碎又不太重要的訪問函式, 你應該直接使用公有變數來取代它們, 這樣可以避免額外的函式呼叫開銷. 當新增更多功能時, 你可以用屬性(property)來保持語法的一致性.

(譯者注: 重視封裝的面向物件程式設計師看到這個可能會很反感, 因為他們一直被教育: 所有成員變數都必須是私有的! 其實, 那真的是有點麻煩啊. 試著去接受Pythonic哲學吧)

另一方面, 如果訪問更復雜, 或者變數的訪問開銷很顯著, 那麼你應該使用像 get_foo()set_foo() 這樣的函式呼叫. 如果之前的程式碼行為允許通過屬性(property)訪問 , 那麼就不要將新的訪問函式與屬性繫結. 這樣, 任何試圖通過老方法訪問變數的程式碼就沒法執行, 使用者也就會意識到複雜性發生了變化.

11. 命名:

應該避免的名稱

  1. 單字元名稱, 除了計數器和迭代器.
  2. 包/模組名中的連字元(-)
  3. 雙下劃線開頭並結尾的名稱(Python保留, 例如__init__)

命名約定

  1. 所謂"內部(Internal)"表示僅模組內可用, 或者, 在類內是保護或私有的.
  2. 用單下劃線(_)開頭表示模組變數或函式是protected的(使用import * from時不會包含).
  3. 用雙下劃線(__)開頭的例項變數或方法表示類內私有.
  4. 將相關的類和頂級函式放在同一個模組裡. 不像Java, 沒必要限制一個類一個模組.
  5. 對類名使用大寫字母開頭的單詞(如CapWords, 即Pascal風格), 但是模組名應該用小寫加下劃線的方式(如lower_with_under.py). 儘管已經有很多現存的模組使用類似於CapWords.py這樣的命名, 但現在已經不鼓勵這樣做, 因為如果模組名碰巧和類名一致, 這會讓人困擾.

命名:第一、模組名、包名稱、方法名、函式名、例項變數名、函式引數名、區域性變數名這些應該使用小寫字母加下劃線的方式,例如,function_name;第二、類名、自定義異常名,應該採用駝峰的命名方式,例如,ClassName;第三、全域性變數名應該使用大寫字母加下劃線的方式,例如,GLOBAL_VAL_NAME

  • 生成器:生成器可以有效的節省記憶體佔用情況,可以按需使用生成器。
  • 預設引數值:定義一個函式式,我們為了應對某些特例情況而新增幾個引數,但是大多數情況下是用不到的,我們可以採用預設引數值的方式應對這些特例呼叫問題,這裡需要注意,預設引數值不要使用可變物件,例如,列表、字典等。
  • True/False的求值:儘量的使用隱式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被認為是false,我們在獲取這些返回值時可以用隱式的false,例如,返回的foo是一個空列表,我們可以用if foo:來判斷它是否為“空”,而不是if foo==[]:,這樣不僅更加易讀,而且能夠避免犯錯。
  • 過時的語言特性:在很多程式碼裡面習慣於使用filter、map、reduce這類語言特性,儘可能使用列表推導或者for迴圈替代。