[英]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.