python的一些性能上的細節

1.合併拼接字符串

你想將幾個小的字符串合併爲一個大的字符串
解決方案
若是你想要合併的字符串是在一個序列或者 iterable 中,那麼最快的方式就是使用
join() 方法。好比:
>>> parts = ['Is', 'Chicago', 'Not', 'Chicago?']
>>> ' '.join(parts)
'Is Chicago Not Chicago?'
>>> ','.join(parts)
'Is,Chicago,Not,Chicago?'
>>> ''.join(parts)
'IsChicagoNotChicago?'
>>>
初看起來,這種語法看上去會比較怪,可是 join() 被指定爲字符串的一個方法。 這樣作
的部分緣由是你想去鏈接的對象可能來自各類不一樣的數據序列(好比列表,元組,字典,
文件,集合或生成器等), 若是在全部這些對象上都定義一個 join() 方法明顯是冗餘
的。 所以你只須要指定你想要的分割字符串並調用他的 join() 方法去將文本片斷組合起
來。
若是你僅僅只是合併少數幾個字符串,使用加號(+)一般已經足夠了:
>>> a = 'Is Chicago'
>>> b = 'Not Chicago?'
>>> a + ' ' + b
'Is Chicago Not Chicago?'
>>>
加號(+)操做符在做爲一些複雜字符串格式化的替代方案的時候一般也工做的很好,比
如:
>>> print('{} {}'.format(a,b))
Is Chicago Not Chicago?
>>> print(a + ' ' + b)
Is Chicago Not Chicago?
>>>
若是你想在源碼中將兩個字面字符串合併起來,你只須要簡單的將它們放到一塊兒,不須要
用加號(+)。好比:
>>> a = 'Hello' 'World'
>>> a
'HelloWorld'
>>>
討論
字符串合併可能看上去並不須要用一整節來討論。 可是不該該小看這個問題,程序員通
常在字符串格式化的時候由於選擇不當而給應用程序帶來嚴重性能損失。
最重要的須要引發注意的是,當咱們使用加號(+)操做符去鏈接大量的字符串的時候是非
常低效率的, 由於加號鏈接會引發內存複製以及垃圾回收操做。 特別的,你永遠都不該
像下面這樣寫字符串鏈接代碼:
s = ''
for p in parts:
    s += p
這種寫法會比使用 join() 方法運行的要慢一些,由於每一次執行+=操做的時候會建立一
個新的字符串對象。 你最好是先收集全部的字符串片斷而後再將它們鏈接起來。
一個相對比較聰明的技巧是利用生成器表達式(參考1.19小節)轉換數據爲字符串的同時合
並字符串,好比:
>>> data = ['ACME', 50, 91.1]
>>> ','.join(str(d) for d in data)
'ACME,50,91.1'
>>>
一樣還得注意沒必要要的字符串鏈接操做。有時候程序員在沒有必要作鏈接操做的時候仍然
畫蛇添足。好比在打印的時候:
print(a + ':' + b + ':' + c) # Ugly
print(':'.join([a, b, c])) # Still ugly
print(a, b, c, sep=':') # Better
當混合使用I/O操做和字符串鏈接操做的時候,有時候須要仔細研究你的程序。 好比,考
慮下面的兩端代碼片斷:
# Version 1 (string concatenation)
f.write(chunk1 + chunk2)
# Version 2 (separate I/O operations)
f.write(chunk1)
f.write(chunk2)
若是兩個字符串很小,那麼第一個版本性能會更好些,由於I/O系統調用天生就慢。 另外
一方面,若是兩個字符串很大,那麼第二個版本可能會更加高效, 由於它避免了建立一
個很大的臨時結果而且要複製大量的內存塊數據。 仍是那句話,有時候是須要根據你的
應用程序特色來決定應該使用哪一種方案。程序員

若是你準備編寫構建大量小字符串的輸出代碼, 你最好考慮下使用生成器
函數,利用yield語句產生輸出片斷。好比:
def sample():
    yield 'Is'
    yield 'Chicago'
    yield 'Not'
    yield 'Chicago?app

這種方法一個有趣的方面是它並無對輸出片斷到底要怎樣組織作出假設。 例如,你可
以簡單的使用 join() 方法將這些片斷合併起來:
text = ''.join(sample())
或者你也能夠將字符串片斷重定向到I/O:
for part in sample():
    f.write(part)函數

再或者你還能夠寫出一些結合I/O操做的混合方案:
def combine(source, maxsize):
    parts = []
    size = 0
    for part in source:
        parts.append(part)
        size += len(part)
        if size > maxsize:
            yield ''.join(parts)
            parts = []
            size = 0
        yield ''.join(parts)
# 結合文件操做
with open('filename', 'w') as f:
    for part in combine(sample(), 32768):
        f.write(part)性能

這裏的關鍵點在於原始的生成器函數並不須要知道使用細節,它只負責生成字符串片斷就
行了。
 spa

相關文章
相關標籤/搜索