beg = time.time() a = "this is a test sting a" b = "this is another test string 测试测试测试ing" res = ''
for i in range(count): if i%2 == 0: res = res + a + ":"+str(i) else: res = res + b+ ":"+str(i) print("time cost +: %s",time.time()-beg)
beg = time.time() for i in range(count): if i%2 == 0: res += a + ":"+str(i) else: res += b+ ":"+str(i) print("time cost +=: %s",time.time()-beg)
beg = time.time() for i in range(count): if i%2 == 0: res = "{} {} {} {}".format(res,a,":",str(i)) else: res = "{} {} {} {}".format(res,b,":",str(i)) print("time cost format: %s",time.time()-beg)
res = [] beg = time.time() for i in range(count): if i%2 == 0: res+=[a,":",str(i)] else: res+=[b,":",str(i)] result = " ".join(res) print("time cost join list: %s",time.time()-beg)
res = 1 beg = time.time() for i in range(count): if i%2 == 0: res = res + i else: res = res + i/2 print("time cost + num : %s",time.time()-beg)
res = 1 beg = time.time() for i in range(count): if i%2 == 0: res += i else: res += i/2 print("time cost += num: %s",time.time()-beg)
var a = "this is a test" var b = "this is another test" var c string
func testAdd() { t := time.Now() for i := 0; i < count; i++ { c = c + a + b } fmt.Println("test add:", time.Now().Sub(t)) }
func testPlus() { t := time.Now() for i := 0; i < count; i++ { c += a + b } fmt.Println("test plus:", time.Now().Sub(t)) }
func testArray() { d := []string{} t := time.Now() for i := 0; i < count; i++ { d = append(d, a, b) } strings.Join(d, "") fmt.Println("test array:", time.Now().Sub(t))
}
func main() { testAdd() testPlus() testArray() }
测试结果:
1 2 3 4 5 6 7 8 9
╰─$ go run testgo/string_plus.go test add: 6.464752503s test plus: 19.349181857s test array: 10.107554ms
─$ go run testgo/string_plus.go //count=20000 test add: 1.046215762s test plus: 3.233030314s test array: 4.82766ms
from cStringIO import StringIO import timing, commands, os from sys import argv
def method1(): out_str = '' for num in xrange(loop_count): out_str += `num` ps_stats() return out_str
def method2(): from UserString import MutableString out_str = MutableString() for num in xrange(loop_count): out_str += `num` ps_stats() return out_str
def method3(): from array import array char_array = array('c') for num in xrange(loop_count): char_array.fromstring(`num`) ps_stats() return char_array.tostring()
def method4(): str_list = [] for num in xrange(loop_count): str_list.append(`num`) out_str = ''.join(str_list) ps_stats() return out_str
def method5(): file_str = StringIO() for num in xrange(loop_count): file_str.write(`num`) out_str = file_str.getvalue() ps_stats() return out_str
def method6(): out_str = ''.join([`num` for num in xrange(loop_count)]) ps_stats() return out_str
if len(argv) == 2: call_method(argv[1]) else: print "Usage: python stest.py <n>\n" \ " where n is the method number to test"
Results: Twenty thousand integers
In the first test 20,000 integers were concatenated into a string 86kb long.
Concatenations per second Process size (kB) Method 1 3770 2424 Method 2 2230 2424 Method 3 29,600 2452 Method 4 83,700 3028 Method 5 90,900 2536 Method 6 119,800 3000
Results: Five hundred thousand integers
Next I tried a run of each method using 500,000 integers concatenated into a string 2,821 kB long. This is a much more serious test and we start to see the size of the python interpreter process grow to accomodate the data structures used in the computation.
Concatenations per second Process size (kB) Method 3 17,100 8,016 Method 4 74,800 22,872 Method 5 94,900 10,480 Method 6 102,100 22,844
Conclusions
I would use Method 6 in most real programs. It’s fast and it’s easy to understand. It does require that you be able to write a single expression that returns each of the values to append. Sometimes that’s just not convenient to do - for example when there are several different chunks of code that are generating output. In those cases you can pick between Method 4 and Method 5.
Method 4 wins for flexibility. You can use all of the normal slice operations on your list of strings, for insertions, deletions and modifications. The performance for appending is pretty decent.
Method 5 wins out on efficiency. It’s uses less memory than either of the list methods (4 & 6) and it’s faster than even the list comprehension for very large numbers of operations (more than about 700,000). If you’re doing a lot of string appending cStringIO is the way to go.