天天看點

python程式設計規範系列--建議08~18

本系列來自《編寫高品質代碼 改善python程式的91個建議》的讀書筆記整理。python程式設計規範系列--建議08~18

  本系列來自《編寫高品質代碼 改善python程式的91個建議》的讀書筆記整理。

   本章主要内容

建議8:利用assert語句來發現問題

建議9:資料交換值時不推薦使用中間交換變量

建議10:充分利用Lazy evaluation的特性

建議11:了解枚舉替代實作的缺陷

建議12:不推薦使用type來進行類型檢查

建議13:盡量轉換為浮點類型再做除法

建議14:警惕eval()的安全漏洞

建議15:使用enumerate()擷取序列疊代的索引和值

建議16:厘清==與is的适用場景

建議17:考慮相容性,盡可能使用Unicod

建議18:建構合理的包層次來管理module

    1)__debug__的值預設為True,且隻讀,無法修改(py2.7)。

    2)斷言是有代價的,對性能産生一定影響。禁用斷言的方法是在運作腳本的時候加上-O标記(不優化位元組碼,而是忽略與斷言相關的語句)。

    使用斷言注意點:

    1)不要濫用,這是使用斷言的最基本的原則;

    2)如果Python本身的異常能夠處理就不要再使用斷言;

    3)不要使用斷言來檢查使用者的輸入;

    4)在函數調用後,當需要确認傳回值是否合理時可以使用斷言;

    5)當條件時業務邏輯繼續下去的先決條件時,可以使用斷言。

1 >>> from timeit import Timer
2 >>> Timer('temp=x;x=y;y=temp','x=2;y=3').timeit()
3 0.03472399711608887
4 >>> Timer('x,y=y,x','x=2;y=3').timeit()
5 0.031581878662109375      

    Lazy evaluation常被譯作“延時計算”或“惰性計算”,指的是僅僅在真正需要執行計算的時候才計算表達式的值。典型例子:生成器表達式。

    1)避免不必要的計算,帶來性能上的提升;

    2)節省空間,使用無限循環的資料結構成為可能。

    1)替代方法:使用類屬性;借助函數;使用collections.namedtuple.

1 >>> from collections import namedtuple
2 >>> Seasons=namedtuple('Seasons','Spring Summer Autumn Winter')._make(xrange(4))
3 >>> print Seasons
4 Seasons(Spring=0, Summer=1, Autumn=2, Winter=3)
5 >>> print Seasons.Autumn
6 2      

    2)替代缺陷:允許枚舉值重複;支援無意義的操作.

1 >>> Seasons._replace(Spring=2) # 不合理
2 Seasons(Spring=2, Summer=1, Autumn=2, Winter=3)
3 >>> Seasons.Summer+Seasons.Autumn == Seasons.Winter # 無意義
4 True      

    3)py2.7的替代方案(py3.4後引入Enum類型):flufl.enum

1 from flufl.enum import Enum
 2 
 3 
 4 class Seasons(Enum):
 5     Spring = "Spring"
 6     Summer = 2
 7     Autumn = 3
 8     Winter = 4
 9 
10 Seasons = Enum('Seasons', 'Spring Summer Autumn Winter')
11 print Seasons
12 print Seasons.Summer.value          

    1)基于内建類型擴充的使用者自定義類型,type函數并不能準确傳回結果;

    2)在舊式類中,所有類的執行個體的type值都相等。

    3)可以用isinstance()函數檢查。

        當涉及除法運算的時候盡量先将操作數轉換成浮點類型再做運算。

        浮點數不精确性導緻的無限循環:

1 >>> i=1
2 >>> while i!=1.5:
3 ... i=i+0.1
4 ... print i      

1 # -*-coding:UTF-8 -*-
 2 
 3 import sys
 4 from math import *
 5 
 6 
 7 def ExpCalcBot(string):
 8     try:
 9         print 'Your answer is', eval(string)
10     except NameError:
11         print "The expression you enter is not valid."
12 
13 
14 while True:
15     print 'Please enter a number or operation. Enter e to complete. '
16 
17     inputStr = raw_input()
18     if inputStr == 'e':
19         sys.exit()
20     elif repr(inputStr) != ' ':
21         ExpCalcBot(inputStr)      

輸入:__import__("os").system("dir")   顯示目前目錄下的所有檔案.

        __import__("os").system("del */Q")   删除目前目錄下的所有檔案.

        是以,在實際應用過程中國呢如果使用對象不是信任源,應該盡量避免使用eval,在需要使用eval的地方可以用安全性更好的ast.literal_eval替代。

        注意,在擷取疊代過程中字典的key和value,應該使用如下iteritems()方法。

1 >>> person={'name': 'Josn', 'age': 19, 'hobby': 'football'}
2 >>> for k,v in person.iteritems():
3 ... print k, ":", v      

1 >>> a="Hi"
 2 >>> b="Hi"
 3 >>> a is b
 4 True
 5 >>> a==b
 6 True
 7 >>> a1 ="I am using long string for testing" # 注意區分
 8 >>> b1 ="I am using long string for testing"
 9 >>> a1 is b1
10 False
11 >>> a1==b1
12 True      
python程式設計規範系列--建議08~18

    is:表示的是對象辨別符,檢查對象的辨別符是否一緻,也就是比較兩個對象在記憶體中是否擁有同一塊記憶體空間;

    ==:表示的是值相等,用來判斷兩個對象的值是否相等,可以被重載。

    字元串駐留(string interning)機制:對于較小的字元串,為了提高系統性能會保留其值的一個副本,當建立新的字元串時直接指向該副本即可。

建議17:考慮相容性,盡可能使用Unicode

    python内建的字元串有兩種類型:str和Unicode,共同祖先為basestring。

    windows本地預設編碼是CP936。

python程式設計規範系列--建議08~18

    解碼:str.decode([編碼參數[,錯誤處理]])  

    編碼:str.encode([編碼參數[,錯誤處理]])

    錯誤處理參數有3種方式:

        (1)strict:預設值,抛出UnicodeError異常;

        (2)ignore:忽略不可轉換的字元;

        (3)replace:将不可轉換字元用?代替。

    有些軟體在儲存UTF-8編碼時,會在檔案最開始地方插入不可見的BOM,可以利用codecs解決。

1 import codecs
2 
3 
4 content = open('manage.py', 'r').read()
5 
6 if content[:3] == codecs.BOM_UTF8:
7     content = content[:3]
8 
9 print content.decode("utf-8")      

    編碼聲明的三種方式:

1 # coding=<encoding name> #方式一
2 #!/usr/bin/env python
3 
4 # -*- coding:<encoding name> -*- #方式二
5 
6 #!/usr/bin/env python
7 # vim:set fileencoding=<encoding name> #方式三      

    包中__init__.py檔案的作用:1)使包和普通目錄區分;

              2)在該檔案中聲明子產品級别的import語句進而使其變成包級别可見;

              3)通過該檔案中定義__all__變量,控制需要導入的子包或者子產品。

    使用包的好處:

    1)合理組織代碼,便于維護和使用;

    2)能夠有效地避免名稱空間沖突。

PS:如果你覺得文章對你有所幫助,别忘了推薦或者分享,因為有你的支援,才是我續寫下篇的動力和源泉!

  • 作者:

    zhangbc

    出處:

    http://www.cnblogs.com/zhangbc/

    格言:

    我願意做一隻蝸牛,慢慢地向前爬,不退縮,不洩氣,做好自己,立足當下,展望未來!

    本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

  • posted @

    2019-01-18 21:44 

    天堂的鴿子 

    閱讀(548) 

    評論(2) 

    編輯 

    收藏 

    舉報

    繼續閱讀