像Java这样的Python中有什么东西StringBuffer
吗?由于字符串在Python中也是不可变的,因此在循环中编辑它们效率很低.
如果仅是如下所示的字符串串联,则立即完成。
test_str = "abcdefghijklmn123456789"
str1 = ""
str2 = ""
start = time.time()
for i in range(1, 100001):
str1 = str1 + test_str
str2 = str2 + test_str
if i % 20000 == 0:
print("time(sec) => {}".format(time.time() - start))
start = time.time()
Run Code Online (Sandbox Code Playgroud)
恒定的处理时间
time(sec) => 0.013324975967407227
time(sec) => 0.020363807678222656
time(sec) => 0.009979963302612305
time(sec) => 0.01744699478149414
time(sec) => 0.0227658748626709
Run Code Online (Sandbox Code Playgroud)
莫名其妙地,将串联字符串分配给另一个变量会使过程变得越来越慢。
test_str = "abcdefghijklmn123456789"
str1 = ""
str2 = ""
start = time.time()
for i in range(1, 100001):
str1 = str1 + …
Run Code Online (Sandbox Code Playgroud) 为什么,在CPython中呢
def add_string(n):
s = ''
for _ in range(n):
s += ' '
Run Code Online (Sandbox Code Playgroud)
需要线性时间,但是
def add_string_in_list(n):
l = ['']
for _ in range(n):
l[0] += ' '
Run Code Online (Sandbox Code Playgroud)
采取二次时间?
证明:
Timer(partial(add_string, 1000000)).timeit(1)
#>>> 0.1848409200028982
Timer(partial(add_string, 10000000)).timeit(1)
#>>> 1.1123797750042286
Run Code Online (Sandbox Code Playgroud)
Timer(partial(add_string_in_list, 10000)).timeit(1)
#>>> 0.0033865350123960525
Timer(partial(add_string_in_list, 100000)).timeit(1)
#>>> 0.25131178900483064
Run Code Online (Sandbox Code Playgroud)
当添加的字符串的引用计数为1时,CPython会对字符串添加进行优化.
这是因为Python中的字符串是不可变的,因此通常无法编辑它们.如果字符串存在多个引用并且它已被突变,则两个引用都将看到更改的字符串.这显然不是必需的,因此多个引用不会发生突变.
但是,如果只有一个对字符串的引用,那么改变该值只会更改该一个引用的字符串,这需要更改它.您可以测试这可能是因为:
from timeit import Timer
from functools import partial
def add_string_two_references(n):
s = ''
for _ in range(n):
s2 = s
s += ' '
Timer(partial(add_string_two_references, 20000)).timeit(1)
#>>> …
Run Code Online (Sandbox Code Playgroud)