9個Python編程小貼士

分享一篇文章,沒有什麼奇技淫巧,只是一些簡單的小貼士,貼到這裡用來提醒一下自己:Python編程方面的一些技巧。


1. list切片的技巧 somelist[start:end:stride]

test = [1, 2, 3, 4, 5]# 從索引最開始到結束,每隔兩個取出一個# 實際上就是肉眼數的奇數位,索引的偶數位odds = test[::2]print(odds) # 結果 -> [1, 3, 5]# 從索引第一位到結束,每隔兩個取出一個# 實際上就是肉眼數的偶數位,索引的奇數位evens = test[1::2]print(evens) # 結果 -> [2, 4]# 對於byte的字元串來說還有神奇的特效(only byte)byte_str = b"abcd"print(byte_str[::-1]) # 結果 -> dcba# 盡量不要很複雜的切片方式,盡量能夠多次解決複雜# 不要同時出現start end stride三個參數

2. 多使用列表表達式

# 1. 例子沒有# list, dict, set都有對列表表達式的支持# 列表表達式代替使用map和filter,可以避免寫lambda函數# 2. 例子# 列表表達式處理多重for循環martix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]flat_list = [x for row in martix for x in row]print(flat_list) # 結果 -> [1, 2, 3, 4, 5, 6, 7, 8, 9]# 拆解代碼大致就是:new_list = []for row in martix: for x in row: new_list.append(x)# 3.例子# 從一個列表中找出一個數字大於4且是偶數的a = [1, 2, 3, 4, 5, 6, 7, 8, 9]# 第一種b = [x for x in a if x > 4 if x % 2 ==0]# 第二種c = [x for x in a if x > 4 and x % 2 ==0]# 結果都是一樣的,只是判斷上的區別# Tips:# 列表表達式能用就盡量用,可以縮減一些代碼量,但是不要寫的過於複雜# 太複雜的表達式,查bug更難找,而且也不利於別人進行維護

3. 數據量大的時候盡量使用生成器表達式代替列表表達式

# 原因很簡單,列表表達式需要開闢較大的內存空間進行存儲"""官方解釋: 生成器表達式,它是對推導和生成器的一種泛化。生成器在運行時不會將整個輸出序列呈現出來,而是會估值為迭代器,這個迭代器每次可以根據生成器表達式產生一項數據。"""# 1. 例子# 讀取一個多行文本,統計每一行的長度it = (len(x) for x in open("<文件路徑>/<文件名>.<文件後綴>")print(it) # 結果 -> <generator object <genexpr> at 某個內存地址># 需要輸出時就用nextprint(next(it))

4. 使用enumerate代替range

# 原因很簡單,封裝的比range好test = ["vannila", "chocolate", "pecan", "strawberry"]# 第一種for i , flavor in enumerate(test): print("%d: %s" % (i + 1, flavor))# 結果如下>>>1: vannila2: chcolate3: pecan4: strawberry# 解釋一下: i + 1 實際上就是為了更好看,如果不i + 1,實際上就是索引的位置.# 第二種for i , flavor in enumerate(test, 1): print("%d: %s" % (i, flavor))# 結果一樣, 實際上就是在enumerate的函數中已經封裝了# 顯得更簡便,而且同時能輸出索引位置或輸出實際中的計數位

5. 合理利用try/except/else/finally

# except的例子就不說了,用過都知道# 直接上else的例子# 函數的功能就是: 載入一個json,返回對應key的值def load_json_key(data, key) try: result_dict = json.loads(data) except ValueError as err: raise KeyError from err else: return result_dict[key]"""解釋: 實際上這個else可要可不要,因為寫在try裡面也是可以的 但是如果為了代碼的可閱讀性,else是一個很必要的東西 代碼閱讀上就知道try裡面是代碼中可能存在錯誤的的地方 如果寫在一堆的話,還有錯誤,那你的except就要增加多幾個了 而且寫代碼也並不建議嵌套try-except,畢竟那不服合代碼的風格."""# finally的話,實際上就一個代碼清理的過程# 一般用在IO或者資料庫讀寫上,用來關閉流, 例子就不寫了.

6. 線程方面的---使用concurrent.futures,實現並行計算

# coding: utf-8 from concurrent.futures import ThreadPoolExecutor as Pool# from multiprocessing import Pool import requestsimport timeurls = ["http://www.gzcc.cn", "http://jwxw.gzcc.cn", "http://www.baidu.com", "http://www.qq.com", "http://www.163.com", "http://www.sohu.com"]def task(url, timeout=10): return requests.get(url=url, timeout=timeout)if __name__ == "__main__": start_1 = time.time() for each_url in urls: response = task(url=each_url) print("%s, %s" % (response.url, response.status_code)) end_1 = time.time() print("順序執行的時長: %f" % (end_1 - start_1)) start_2 = time.time() pool = Pool(max_workers=4) # pool = Pool(processes=4) processes = pool.map(task, urls) for each_process in processes: print("%s, %s" % (each_process.url, each_process.status_code)) end_2 = time.time() print("並行執行的時長: %f" % (end_2 - start_2))# 第一種的結果: 1.4s# 第二種的結果: 0.4s# 結果的提升是肯定有的,但是和網路情況有關係。# 關於導入的包 concurrent.future# 對於這個包裡面的ThreadPoolExecutor和multiprocessing的Pool對比,作用實際上差不多,具體時間差異我還沒怎麼測試過.# 但是如果你認真看源碼的話會發現,實際上future的包在process的那一塊也是調用multiprocessing的# 按照源碼的意思就是在子線程中運行多個python的解釋器,從而實現並行.# 但是一般的代碼或者多線程爬蟲上基本體會不出,因為爬蟲的核心還是在網路速度上,而一般的代碼也沒必要# 除非計算矩陣或者其他的需要巨大計算量的時候再考慮使用.

7. 與分析方面有關的---重視精度時使用decimal

# 例子rate = 1.45seconds = 3 * 60 + 42cost = rate * seconds / 60print(cost) # 結果很奇怪: 5.364999999999999# 這時候可能會想到用round的函數# 1、如果這時你的需求是不足一分也當一分的計算# 類似於向上取整round的方法會把結果變成5.36而不是5.37# 2、如果沒有要求的時候使用round就可以了# # 針對第一種問題,就引出一個decimal的方法了,改寫一下from decimal import Decimalrate = Decimal("1.45")seconds = Decimal(3 * 60 + 42)cost = rate * seconds / Decimal(60)print(cost) # 結果 -> 5.365# 重點說下這裡。# 有個很奇怪的地方,有興趣的可以研究下為什麼。# 把rate的那個1.45去掉單引號包圍,再運行就明白為什麼奇怪了# 反觀結果, 5.365貌似也不是我們想要的,這裡就引入一個quantize方法了# 在代碼頂部加上 from decimal import ROUND_UP# cost還是剛剛的costrounded = cost.quantize(Decimal("0.01"), rounding=ROUND_UP)print(rounded) # 結果 -> 5.37# 兜兜轉轉就到結果這裡了.一般這些情況都是對精度要求很高才需要,一般情況就當看不見好了.

8. 協作開發的時候盡量不要寫import *

你的代碼在導包的時候寫了import *,你自己開發是很明白有什麼方法的.但是在協作開發或者開源項目的時候盡量避免.因為其他開發者並不知道裡面的方法是幹啥的.

9. 配置文件獨立化

# 例如一些資料庫的配置,selenium的webdriver的配置,甚至開發的模式配置可以通過一些json格式的配置文件進行維護.# 好處1: 在於這樣管理項目不用"東奔西跑",為了一個全局變數找半天# 好處2: 在協同開發的時候,可以不用變動的代碼的情況下,根據自己的開發環境確定一些全局配置# 缺點的話,實際上也算不上缺點.就是每次都要讀取一次配置文件,代碼的速度會減慢一點點,但是並不礙事.


你想更深入了解學習Python知識體系,你可以看一下我們花費了一個多月整理了上百小時的幾百個知識點體系內容:

【超全整理】《Python自動化全能開發從入門到精通》筆記全放送


推薦閱讀:

Python 家族有多龐大
Python數據分析及可視化實例之CentOS7.2+Python3x+Flask部署標準化配置流程

TAG:Python | Python入门 |