簡體   English   中英

字典條目中的Python字符串串聯

[英]Python string concatenation in dictionary entries

我必須將許多短字符串連接到字典條目中,我意識到它的運行速度非常慢(大約是二次方)。 但是,如果事先將字符串連接起來,然后添加到字典中,則連接時間幾乎是線性的。

這是一個簡單的例子。 此函數基本上連接許多字符串,並創建一個字典,其中包含包含連接字符串的單個條目。 第一個函數直接在條目“ d [key] + = str(num)”上執行,第二個函數在字符串“ out_str + = str(num)”上執行。 下面是打印的時間,可以看到二次和線性行為。

我不知道開銷是從哪里來的。 謝謝!

def method1(loop_count):
    """ String concatenation on dictionary entry directly (slow)"""
    out_str = ''
    d={}
    key = 'key' 
    d[key] = ''
    for num in range(loop_count):
        d[key] += str(num)
    return d

def method2(loop_count):
    """ Concatenation 'on string' and then add to dictionary (fast) """
    out_str = ''
    d={}
    key = 'key' 
    for num in range(loop_count):
        out_str += str(num)

    d[key] = out_str
    return d

def method3(loop_count):
    """ Concatenation 'on string' and then add to dictionary (fast) """
    out_str = ''
    d={}
    key = 'key'

    out_str = ''.join(str(n) for n in range(loop_count))

    d[key] = out_str
    return d

from timeit import default_timer as timer
import numpy as np
for p in range(10,20):
    t0 = timer()
    method1(np.power(2,p))
    t1 = timer()
    method2(np.power(2,p))
    t2 = timer()
    method3(np.power(2,p))
    t3 = timer()
    print("2^{}:\t{:4.2g}\t{:4.2g}\t{:4.2g}".format(p, t1-t0, t2-t1, t3-t2))

        in dict   +=    join
2^10:   0.0003  0.0002  0.0002
2^11:   0.00069 0.0004  0.00038
2^12:   0.0017  0.00079 0.00076
2^13:   0.0057  0.0016  0.0015
2^14:   0.021   0.0032  0.0031
2^15:   0.095   0.0065  0.0065
2^16:   0.77    0.013   0.013
2^17:    3.2    0.026   0.027
2^18:     15    0.052   0.052
2^19:     67     0.1    0.11

注意:這不是嚴格關於有效字符串連接的問題。 它是關於何時在字符串連接中進行字符串優化的。

注2:我使用“ join”慣用語添加了第三種方法,它花費的時間與+ =完全相同


答案表明,這似乎是一個優化問題。 進一步的測試似乎證明了這一點。 以下代碼顯示+ =重用了許多字符串,無論字典條目中的串聯是否沒有:

a=''
for n in range(10):
    print(id(a))
    a+=str(n)

140126222965424
140126043294720
140126043294720
140126043294720
140126043294720
140126043294720
140126043294720
140126043294720
140126042796464
140126042796464

d={}
d['key']=''
for n in range(10):
    print(id(d['key']))
    d['key']+=str(n)

140126222965424
140126042643120
140126042643232
140126042643176
140126042643120
140126042643232
140126042643176
140126042643120
140126042761520
140126042761456

我仍然想知道為什么會這樣。 謝謝!

“ E.Coms”鏈接的文章指向舊的郵件列表條目: https ://mail.python.org/pipermail/python-dev/2004-August/046686.html,其中涉及類似以下代碼:

s = ''
for x in y:
  s += some_string(x)

提:

這個問題很重要,因為性能差異巨大-我們並不是在說快2倍甚至10倍,而是快大約N倍,其中N是輸入數據集的大小。

有趣,因為我認為

out_str = ''.join(str(n) for n in range(loop_count))

會比

out_str = ''
for num in range(loop_count):
    out_str += str(num)

但據我所知,它們具有相同的性能。 我認為我做這個假設是因為重復的消息說str.join()是一件“好事”

不確定是否能回答問題,但我發現歷史很有趣!

如下面的juanpa.arrivillaga所示, method1速度很慢,因為將對字符串的引用存儲在其他位置會使上述優化無效。 同樣,執行額外的字典查找也會產生O(n)的開銷,但是在這種情況下,這種小開銷主要是由創建字符串的n個副本的O(n ^ 2)工作而不是僅由攤銷的O( n)優化允許的版本

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM