python | 改善Python程序建議- Part1

Python在學完初級語法以後都會面臨一個瓶頸,不知道接下來要學什麼,也不知道如何獨立完成一個實戰項目。除了多加練習以外,還應該增長知識攝入,相信量便會引發質變。
 
python學習的三個階段:
第一個階段:掌握Python的語法和一些經常使用庫的使用
能夠邊學語法邊刷Leetcode
第二個階段:中級,掌握本身特定領域的庫,掌握pythonic寫法,很是熟悉Python的特性
這個階段瞭解python工程的文件佈局,總結如何寫出pythonic的代碼;
有機會能夠查看源碼,完全瞭解python的核心機制。(可參考《Python源碼剖析——深度探索動態語言核心技術》)
第三階段::高級,從整個工程項目着眼,考慮document,distribution,性能優化等
 
這個系列主要是總結一些《改善python程序的91個建議》的學習筆記,但願能夠對本身和讀者有所幫助。本文是該系列第一部分,第二部分請見  Part2
 
1 格式化輸出
官方推薦 str.format()
e.g. print (‘{greet} from {language}.’.format(greet = 「hello world」, language = ‘python’))
 
2 模塊和包
包和模塊的命令採用小寫、單數形式,並且短小。
包一般僅做爲命名空間,如只包含空的__init__.py文件。
 
3 與C的不一樣
· 三元操做符 eg: x if C else Y
· switch case
 
4 註釋的使用
三對"""
· 要清楚地描述方法的功能,並對參數,返回值以及可能發生的異常進行說明;
· 推薦在文件頭包含copyright 聲明,模塊的描述等,若有必要,能夠考慮加入做者的信息及變動記錄;
e.g.

"""
    Licensed Materials - Property of CorpA
    (C) Copyright A Corp.1999, 2011 All Rights Reserved
    CopyRight statement and purpose....
    ------------------------------------------------------
    File Name : comments.py
    Description: description what the main function of this file

    Author: LF
    change Activity:
            list the change activity and time and author information
    -----------------------------------------------------------
"""
 
5 代碼編寫建議
· 適當添加空行使代碼更爲優雅、合理
· 保持上下文的易理解性,若是一個函數須要調用另外一個函數,最好放在一塊兒
· 避免過長代碼
· 空格的使用
 
6 函數編寫
· 函數設計要儘可能短小
· 合理的參數設定 參數數量不該過多 同時要考慮向下兼容
eg:前一個 def readfile(filename) 版本升級添加日誌 def readfile(filename,logger) —> 應用缺省參數 def readfile(filename,logger=xxx)
· 一個函數只作一件事情,儘可能保證函數語句粒度的一致性
· 使用異常處理返回錯誤,保證經過單元測試等
 
7 將常量集中到一個文件
· 常量的命名 通常是全大寫字母 中間用下劃線鏈接 這只是一直約定俗成的風格。如TOTAL,MAX_OVERFLOW
· 經過自定義的類實現常量功能 —>要求:命名所有大寫 和 值一旦綁定不可修改 能夠經過異常來解決這個問題
e.g.
class _const:
    class ConstError(TypeError): pass
    class ConstCaseError(ConstError): pass
    
    def __setattr__(self, name, value):
        if self.__dict__.has_key(name):
            raise self.ConstError, "Can't change const. %s" %name
        if not name.isupper():
            raise self.ConstCaseError, \
                'const name "%s" is not all uppercase' %name
        self.__dict__[name] = value

import sys
sys.modules[__name__] = _const()

 8 利用assert 語句來發現問題(斷言)html

assert expression1 ["," expression2]
其中expression1的值會返回True或者False,當值爲False的時候會引起AssertionError,而expression2是可選的,經常使用來傳遞具體的異常信息。但使用斷言有性能成本,使用時需注意。
 
9 數據交換值的時候不推薦使用中間變量
x,y = y,x
10 利用Lazy evaluation 的特性

 延遲計算/惰性計算
- 避免沒必要要的計算
eg: if x or y 當x爲 true時就直接返回 不用計算y
- 節省空間,使用無限循環的數據結構成爲可能
eg:生成器表達式 a= (x for x in range(100))—>不會當即生成數據列表 用的時候纔會生成 print(a[9])
 
11 不推薦使用type()來進行類型檢查
- 基於內建類型擴展的用戶自定義類型 type並不能準確返回結果 好比class A(int)
isinstance(object, classinfo)
#其中,classinfo能夠爲直接或間接類名、基本類型名稱或者由它們組成的元祖
#isinstance(2, float)                    False
#isinstance("a", (str,unicode))      True
12 轉成浮點後再作除法

但py3已經作了更新,除法不會截斷
from __future__ import division
但浮點的運算結果也不必定準確。若是計算對精度要求較高,可使用decimal來進行處理或者將浮點數儘可能擴大爲整數,計算完畢以後再轉換回去,同時浮點數的比較一樣最好可以指明精度。
 
13 警戒eval()安全漏洞
eval()是將字符串改變爲有效的表達式
在實際應用過程當中,若是使用對象不是信任源,應該儘可能避免使用eval,在須要使用eval的地方能夠用安全性更好的ast.literal_eval替代。
 
14 使用enumerate()獲取序列迭代
每次僅在須要的時候纔會產生一個(index,item)對
enumerate(sequence, start=0)
#sequence能夠是list、 set等任何迭代對象
#默認從0開始
#函數返回一個迭代器,可使用next()方法獲取下一個元素
15 區分 is 和 ==
 
16 考慮兼容性,儘量使用Unicode
通常就是向文件傳輸時 先編碼 再到達客戶端時解碼 a=」你好」.encode(「utf-8」) –> a.decode(「utf-8」)
encode和decode中參數 window 通常是gbk liunx等其餘通常是utf-8
 
17 構建合理的包層次來管理module
經過包(Package)來合理的組織項目的層次來管理模塊
包與普通目錄不一樣,在於除了包含常規的python文件(模塊)之外,還包含一個__init__.py文件,同時它容許嵌套。
Package/ __init__.py
    Module1.py
    Molude2.py
    Subpackage/ __init__.py
        Module1.py
        Module2.py
包使用的好處:
- 合理組織代碼,易於維護和使用。如下是一個可供參考的python項目結構:
ProjectName/
|---README
    |----LICENSE
    |----setup.py
    |-----requirements.txt
    |------sample/
    |   |----__init__.py
    |   |----core.py
    |   |----helpers.py
    |------docs/
    |   |------conf.py
    |   |------index.rst
    |------bin/
    |------package/
    |   |-----__init__.py
    |   |-----subpackage/
    |   |-----......
    |------tests/
    |   |------test_basic.py
    |   |------test_advancde.py

- 可以有效地避免名稱空間衝突。python

 18 有節制地使用from….import語句express

· 通常狀況優先使用import a —> print a.xxx
· 有節制地使用from a import xxx —> print xxx
· 儘可能避免使用from a import * —>污染命名空間

19 i+=1 不等於 ++i安全

在python中 ++i 不是自增 +(+1) 即正數取正
同理: –i 不是自減 -(-1) 即負數取反

20 使用with自動關閉資源性能優化

基本上只要是須要close的均可以用with eg:
with open(xx_file_name,'rb') as f:
        f.read()
實際上任何實現了上下文協議的對象的均可以稱爲一個上下文管理器->如 打開/關閉文件,異常處理,斷開流的鏈接,鎖分配等

 

參考:數據結構

《改善python程序的91個建議》函數

https://blog.csdn.net/qq_31603575/article/details/80177153佈局

https://www.cnblogs.com/cotyb/p/5452602.html性能

https://www.cnblogs.com/cotyb/tag/pythonic/單元測試

https://medium.freecodecamp.org/an-a-z-of-useful-python-tricks-b467524ee747

相關文章
相關標籤/搜索