Python/提示與技巧
外觀
< Python
在 Python 中學習許多技巧和竅門:
字符串
[編輯]- 三引號是一種使用單引號和雙引號定義字符串的簡單方法。
- 字符串連接「成本高昂」。使用百分比格式和 str.join() 進行連接:
(但除非您生成的字符串長度超過 500-1000 個字符,否則不必擔心這一點) [1]
print "Spam" + " eggs" + " and" + " spam" # DON'T DO THIS
print " ".join(["Spam","eggs","and","spam"]) # Much faster/more
# common Python idiom
print "%s %s %s %s" % ("Spam", "eggs", "and", "spam") # Also a pythonic way of
# doing it - very fast
優化的 C 模塊
[編輯]多個模塊都有用 C 編寫的優化版本,它們提供了幾乎相同的接口,並且通常比純 Python 實現「快得多」或更節省內存。模塊行為通常在某些方面有所不同,通常是微小的,因此經常使用 C 版本。
這主要是 Python 2.x 的功能,在 Python 3 中已基本被刪除,模塊會自動使用優化的實現(如果有)。[2] 但是,cProfile
/profile
對仍然存在(截至 Python 3.4)。
導入
[編輯]名為 module
或 Module
的模塊的 C 版本稱為 cModule
,並且經常使用 import...as
導入以去掉前綴,如下所示:
import cPickle as pickle
為了兼容性,可以嘗試導入 C 版本,如果 C 版本不可用,則回退到 Python 版本;在這種情況下使用 import...as
是「必需的」,因此代碼不依賴於導入了哪個模塊:
try:
import cPickle as pickle
except ImportError:
import pickle
示例
[編輯]值得注意的示例包括:
- (Python 2.x)
cPickle
用於pickle
,速度最高可提高 1000 倍。 - (Python 2.x)
cStringIO
代替StringIO
,在 Python 3 中由io.StringIO
取代 cProfile
代替profile
– Pythonprofile
增加了顯著的開銷,因此建議在大多數情況下使用cProfile
。- (Python 3.3+ 中不需要)
cElementTree
用於ElementTree
,速度提高 15-20 倍,內存使用量減少 2-5 倍;[3] Python 3.3+ 中不需要,如果可能,會自動使用快速實現。
列表推導和生成器
[編輯]- 列表推導和生成器表達式對於處理小型緊湊循環非常有用。此外,它比普通的 for 循環更快。
directory = os.listdir(os.getcwd()) # Gets a list of files in the
# directory the program runs from
filesInDir = [item for item in directory] # Normal For Loop rules apply, you
# can add "if condition" to make a
# more narrow search.
- 列表推導和生成器表達式可用於使用 zip 或 itertools.izip 處理兩個(或更多)列表
[a - b for (a,b) in zip((1,2,3), (1,2,3))] # will return [0, 0, 0]
數據類型選擇
[編輯]選擇正確的數據類型對於應用程式的性能至關重要。例如,假設您有 2 個列表:
list1 = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
list2 = [{'e': 5, 'f': 6}, {'g': 7, 'h': 8}, {'i': 9, 'j': 10}]
並且您想要找到兩個列表中共有的條目。您可以遍歷一個列表,檢查另一個列表中的共同項:
common = []
for entry in list1:
if entry in list2:
common.append(entry)
對於這樣小的列表,這將正常工作,但對於較大的列表,例如如果每個列表包含數千個條目,則以下方法將更有效,並產生相同的結果:
set1 = set([tuple(entry.items()) for entry in list1])
set2 = set([tuple(entry.items()) for entry in list2])
common = set1.intersection(set2)
common = [dict(entry) for entry in common]
集合在此類函數中針對速度進行了優化。字典本身不能用作集合的成員,因為它們是可變的,但元組可以。如果需要對字典列表執行集合操作,可以將項轉換為元組,將列錶轉換為集合,執行操作,然後轉換回來。這通常比嘗試使用字符串函數複製集合操作要快得多。
其他
[編輯]- 裝飾器可用於處理常見問題,如日誌記錄、資料庫訪問等。
- 雖然 Python 沒有內置函數來展平列表,但您可以使用遞歸函數快速完成這項工作。
def flatten(seq, list = None):
"""flatten(seq, list = None) -> list
Return a flat version of the iterator `seq` appended to `list`
"""
if list == None:
list = []
try: # Can `seq` be iterated over?
for item in seq: # If so then iterate over `seq`
flatten(item, list) # and make the same check on each item.
except TypeError: # If seq isn't iterable
list.append(seq) # append it to the new list.
return list
- 為了阻止 Python 腳本在獨立啟動後立即關閉,請添加以下代碼:
print 'Hit Enter to exit'
raw_input()
- Python 已經內置了 GUI:Tkinter,基於 Tcl 的 Tk。還有更多可用的,例如 PyQt4、pygtk3 和 wxPython。
- 三元運算符:
[on_true] if [expression] else [on_false]
x, y = 50, 25
small = x if x < y else y
- 布爾值作為索引:
b = 1==1
name = "I am %s" % ["John","Doe"][b]
#returns I am Doe
參考文獻
[編輯]- ↑ 'concat vs join - followup' on 'Python Rocks! and other rants 27.8.2004 Weblog of Kent S Johnson'(2004年8月27日).於2008年8月29日查閱.
- ↑ Python 3.0 中的新增功能,Guido van Rossum
- ↑ 「cElementTree 模塊」,2005 年 1 月 30 日,Fredrik Lundh