跳轉到內容

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)。

名為 moduleModule 的模組的 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 - Python profile 會增加顯著的開銷,因此 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]

資料型別選擇

[編輯 | 編輯原始碼]

選擇正確的資料型別對於應用程式的效能至關重要。例如,假設您有兩個列表

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

參考文獻

[編輯 | 編輯原始碼]
  1. "'concat vs join - followup' on 'Python Rocks! and other rants 27.8.2004 Weblog of Kent S Johnson'". August 27, 2004. Retrieved 2008-08-29.
  2. Python 3.0 中的新內容, Guido van Rossum
  3. "cElementTree 模組", January 30, 2005, Fredrik Lundh
華夏公益教科書