本文分享自華為雲社區《不得不知的十個常見PY編碼習慣》,作者:碼樂。 簡介 語言在發展和變化,編碼習慣也在發生改變。這裡簡單聊聊 17個python中常見的編碼習慣或者風格。 1,可變數據結構: 註意在函數變數不要使用它 def foo(x=[]): x.append(1) print(x) >>> ...
本文分享自華為雲社區《不得不知的十個常見PY編碼習慣》,作者:碼樂。
簡介
語言在發展和變化,編碼習慣也在發生改變。這裡簡單聊聊 17個python中常見的編碼習慣或者風格。
1,可變數據結構: 註意在函數變數不要使用它
def foo(x=[]): x.append(1) print(x) >>>foo() [1] >>>foo() [1,1] >>>foo() [1,1,1] def foo(p=None): if p is None: p = [] p.append(1) print(p) foo() [1] foo([2,3,4]) [2,3,4,1]
1.1模塊的迴圈導入
我們定義一個老王模塊,再定義一個小李模塊,相互導入時,將報錯
# laowang.py import xiaoli count =4 def main(): wilma.pr('Hello') if __name__ == '__main__': main() # xiaoli.py import laowang def pr(str): print(str*fired.count) if __name__== '__main__': pr("Ok")
導入問題,如果在使用其他語言 比如 shell 腳本引用 python代碼時,需要將python項目加入 linux環境變數。 <=python2.7
export PYTON_PATH=$PYTHON_PATH:/xxx/xxx/XXXProject
或者編輯 python虛擬環境,添加 setup.py, 然後執行 python install -e .
1.2 基礎規則
該次執行不緩存sys.stdout,直接輸出控制台
@參數 -u unbuffered
執行時帶參數m,以Script方式執行py模塊
@參數 -m
跳過py模塊第一行,允許使用非unix形式
@參數 -x
實體具體選項(set implementation-specific option)
@參數 -X
程式讀取文件內容並執行
file
程式從stdin 讀取
@參數 -
python3 --help # 顯示所有參數
dd
2, 記憶體管理
python 記憶體回收 基於 引用計數 和 分級回收。
2.1 小的整數 和短小字元,python將緩存以便重覆使用
並且is關鍵字,用於判斷兩個引用所指對象是否相同
>>> a = 'gd' >>> b = 'gd' >>> a is b True
== 只判斷值是否相同
a2 = [] b2 = [] >>> a2 is b2 False >>> b2 == a2 True
2.2 對象引用時python基本構成方式
賦值的本質 a=1,實際上時修改globals()字典的值,局部變數值的修改locals()的訪問和修改
>>> a1 very good man >>> globals()['a1'] = 'bad good mm' >>> globals()
2.3 引用對象reference count
sys.getrefcount() 查看對象的引用計數,sys.getrefcount()在查看某個引用時將創建一個臨時引用,所以引用計數將多1
>>> c=[1,2,3]
getrefcount© #這裡c只有一次引用,但是計數時2,因為當前查詢有一次臨時引用
2
引用計數的減少和增加
>>> d=c
getrefcount© # 增加引用d,計數3
3
del d #刪除引用d,c的引用計數又重新為2
2.4 垃圾回收機制 garbage collection
垃圾回收時py 獨占進行的,大大降低py效率,特定條件下自動啟動垃圾回收。
手工回收 gc.collect()
py 運行時分配對象obj allocation 和取消分配對象 deallocation次數被記錄,高於垃圾回收閾值,啟動垃圾回收
gc.get_threshold()查看該閾值,gc.set)threshold()重新設置該閾值
(700, 10, 10) 700表示啟動垃圾回收閾值,10,10表示分別回收的閾值
2.4.1 垃圾回收分代策略 generation,基本假設如下
存活時間越久,越不可能在後面程式中變為垃圾。 這樣所有對象分為0,1,2三代,所有新建對象都是0代。某一對象經歷垃圾回收,仍然存活,那麼它就被歸入下一代對象。
垃圾回收時,一定掃描0代對象,如果0代經過一定次數垃圾回收,下一次對0代和1代掃描清理,
當1代也經歷一次次數垃圾回收,這啟動0,1,2所有對象的掃描
以上gc.get_threshold()返回(700,10,10)兩個表示每10次0代垃圾回收,將配置1次1代垃圾回收,每10次1代垃圾回收,才有1次2代垃圾回收。
2.4.2 兩個對象相互引用,
相互引用構成引用環 reference cycle,該引用環將給上一節2.4.1的垃圾回收帶來困難,
引用環可能構成一些無法使用但引用計數不為0的對象 為了回收該引用環對象,
py複製了每個對象的引用計數為 gc_ref 遍歷所有對象,將每個對象引用的對象相應的gc_ref減1,遍歷結束後,
gc_ref不為0的對象和這些對象的引用對象,以及繼續更新下游引用對象,被爆了,其他對象被回收。
參考 記憶體管理,函數預設參數,動態類型
2.4.3 迭代
可迭代對象 iter
迭代器 iter + next
生成器 特殊迭代器 yield
def yd(): a = 100 yield a yield a*8 yield 8000
2.4.4 抽象方法*(函數)
對象方法(self.對象方法),類方法(@classmethod),靜態方法(@staticmethod)
抽象方法 需要子類實現的方法 用@abc.abstractmethod以及 metaclass = abc.ABCMeta
使得任何繼承自父類的子類必須覆蓋實現抽象方法,否則拋出異常
3,其他概念
閉包 closure
閉包指的是 難以讀取其他函數內部遍歷的函數
實現: 定義在函數內的內部函數可以讀取外層函數變數,從而實現閉包
4,慣例
1,判定dict的key是否存在,使用key in dict而不用 has_key
2,not的位置,使用key not in dict 而不用 no key in dict
3, 使用 dict.get(key[,default])如果key存在,返回,否則返回default
4, 數組字典初始化
dic = {} for k,v in data: group = dic.setdefault(key,[]) #如果存在,返回dic[key],不存在把dic[key]設為defalut並返回 group.append(v) from collections import defaultdic dic = defalutdic(list) for (k,v) in data: dic[key].append(v) #所有key都有一個預設值
迭代一個數組,使用for i,e in enumerate(array) 而不是 for i in range(len(array))
enumerate 還有第二個參數
5,py3元組unpack
first, second,*rest, last = range(10) 0 1 2~8 9
6, 函數參數傳入
def foo(x,y): print(x,y) adict = {'x':1, 'y':2}
foo(**adict) #字典key作為參數名傳入參數值
alist=[1,2] foo(*alist)
7, 字元串連接
name = "Wang" "Hone" # WangHong
8, 解釋器中的
上一次接收器的返回值
9,嵌套列表推導式
[(i,j) for i in range(3) for j in range(i)]
10, print重定向
print >>open('a.txt', 'w+'), 'hello,world'
11,反射
#檢查是否某個自定的類 isinstance(obj, class)
12,Picking是Python數據結構的序列化過程
存儲一個對象,稍後再取出讀取
如何pickle 已存在的對象類型到文件
json = {'name':'jack', 'age':100} json_file = open('json pkl', 'rb') pickle.dump(json.json_file) json_file.dump(json,json_file) json_file.close()
取出
data=pickle.load(json_file)
print(data)
json_file.close()
pickler內建類型和外部方法
類自定義行為
__getinitargs__(self) #
__getnewargs__(self)
Slate 記住它曾經是什麼,以及什麼時候賦值給它 ?
__slate__
為對象類 提供限制,只能賦予固定的屬性名稱
13,對象模型Python3和Python2.x之間的主要區別
Python3的string和unicode區別不復存在,因此__unicode__被取消 __bytes__加入進來(與
python2.7的__str__和__unicode__行為類似),用於心的創建位元組數組的內建方法
py3預設除法變成了true除法,因此__div__取消
__coerce__被取消,因為與其他魔法方法有功能重覆
cmp 取消,與其他魔法方法功能重覆
__nonzero__被重命名為
14,斷點
6.1, 斷點設置後,代碼執行到該位置,程式掛起檢查程式行為 6.2, 異常斷點,到達斷點後要執行的操作 6.3, 斷點屬性,達到斷點時要執行的操作 掛起策略,用於定義在遇到斷點時是否必須掛起應用程式 對其他斷點的依賴, 何時必須擊中斷點 6.4 消息記錄 斷點命中消息,命中斷點時,控制輸出一條日誌消息 堆棧跟蹤 斷點的堆棧跟蹤將命中列印到控制台 6.5 斷點工具 pdb 互動式代碼調試,功能包括 設置斷點,單步調試,進入函數調試,查看當前代碼,查看棧片段,動態改變變數的值 進入pdb交互界面 命令 break 或b設置斷點 continue 或c 繼續執行 list或l 查看當前代碼段 step或s 進入函數 return或r 執行代碼直到當前函數返回 exit或q 中止並退出 next或n 執行下一行 pp 列印變數的值
15, 依賴問題
pycurl 需要contos 7安裝python3-devel
具體過程pycurl-centos7
16, py編譯 發佈流程
1,編譯生成pyc文件,建議增加-O優選項
python3 -O -m compileall -b .
2, 刪除py文件
find . -name "*.py"|xargs rm -rf
3, 刪除__pycache__目錄
find . -name "__pycache__" |xargs rm -rf
4, 打包 tar包
cd .. tar -cjvf xxx.1.1.00.tar.bz2 xxx
5, 或git push到倉庫
git push origin master:master
16 常用內置 魔法函數
iter # 在類中實現,可以直接對類進行迭代 類似於如下形式
obj.next 或 next(obj)
call # 在對象直接 進行調用
obj()
、slate 為對象類 提供限制,只能賦予固定的屬性名稱
__qualname__ # 查看類和當前函數名
>>> D.f.__qualname__
>>> D.f#返回類和函數
通過類字典返回函數,不會 返回函數名
>>> D.__dict__['f'] <function D.f at 0x000001F6C6224670
通過類實例的點運算 查看函數 將直接返回函數
>>> d = D() >>> d.f <bound method D.f of <__main__.D object at 0x000001F6C5F42070>>
查看實例的函數對象
>>> d.f.__func__ <function D.f at 0x000001F6C6224670> >>> d.f.__self__ <__main__.D object at 0x000001F6C5F42070>
17 內置函數 二進位運算
chr 返回整數 i 的字元串格式,如 chr(97) 返回字元 'a' 是 ord的逆運算 chr('8364') (歐元符號)返回 € ord 返回代表單個Unicode字元的 碼點的整數,例如 ord('a')返回整數 97 ord('€') (歐元符號)返回 8364