it-swarm.dev

Python 문자열 연결과 string.join의 속도는 어느 정도입니까?

this thread 에 대한 답변의 의견으로 += 연산자와 ''.join() 사이의 속도 차이가 무엇인지 알고 싶었습니다.

그렇다면 둘 사이의 속도 비교는 무엇입니까?

53
Wayne Werner

From : 효율적인 문자열 연결

방법 1 :

def method1():
  out_str = ''
  for num in xrange(loop_count):
    out_str += 'num'
  return out_str

방법 4 :

def method4():
  str_list = []
  for num in xrange(loop_count):
    str_list.append('num')
  return ''.join(str_list)

이제 나는 그들이 대표하는 것이 아니며 4 번째 방법이 각 항목을 반복하고 참여하기 전에 목록에 추가한다는 것을 알고 있지만 공정한 표시입니다.

문자열 결합은 연결보다 훨씬 빠릅니다.

왜? 문자열은 변경할 수 없으며 제자리에서 변경할 수 없습니다. 하나를 변경하려면 새로운 표현을 만들어야합니다 (두 가지를 연결).

alt text

78
Dominic Bou-Samra

내 원래 코드가 잘못되었습니다. + 연결 속도가 빠릅니다 (특히 최신 버전의 Python)).

시간은 다음과 같습니다.

Iterations: 1,000,000       

Windows 7, Core i7의 Python 3.3

String of len:   1 took:     0.5710     0.2880 seconds
String of len:   4 took:     0.9480     0.5830 seconds
String of len:   6 took:     1.2770     0.8130 seconds
String of len:  12 took:     2.0610     1.5930 seconds
String of len:  80 took:    10.5140    37.8590 seconds
String of len: 222 took:    27.3400   134.7440 seconds
String of len: 443 took:    52.9640   170.6440 seconds

Windows 7, Core i7의 Python 2.7

String of len:   1 took:     0.7190     0.4960 seconds
String of len:   4 took:     1.0660     0.6920 seconds
String of len:   6 took:     1.3300     0.8560 seconds
String of len:  12 took:     1.9980     1.5330 seconds
String of len:  80 took:     9.0520    25.7190 seconds
String of len: 222 took:    23.1620    71.3620 seconds
String of len: 443 took:    44.3620   117.1510 seconds

Linux Mint에서 Python 2.7, 일부 느린 프로세서

String of len:   1 took:     1.8840     1.2990 seconds
String of len:   4 took:     2.8394     1.9663 seconds
String of len:   6 took:     3.5177     2.4162 seconds
String of len:  12 took:     5.5456     4.1695 seconds
String of len:  80 took:    27.8813    19.2180 seconds
String of len: 222 took:    69.5679    55.7790 seconds
String of len: 443 took:   135.6101   153.8212 seconds

그리고 여기 코드가 있습니다 :

from __future__ import print_function
import time

def strcat(string):
    newstr = ''
    for char in string:
        newstr += char
    return newstr

def listcat(string):
    chars = []
    for char in string:
        chars.append(char)
    return ''.join(chars)

def test(fn, times, *args):
    start = time.time()
    for x in range(times):
        fn(*args)
    return "{:>10.4f}".format(time.time() - start)

def testall():
    strings = ['a', 'long', 'longer', 'a bit longer', 
               '''adjkrsn widn fskejwoskemwkoskdfisdfasdfjiz  oijewf sdkjjka dsf sdk siasjk dfwijs''',
               '''this is a really long string that's so long
               it had to be triple quoted  and contains lots of
               superflous characters for kicks and gigles
               @!#(*_#)(*$(*!#@&)(*E\xc4\x32\xff\x92\x23\xDF\xDFk^%#$!)%#^(*#''',
              '''I needed another long string but this one won't have any new lines or crazy characters in it, I'm just going to type normal characters that I would usually write blah blah blah blah this is some more text hey cool what's crazy is that it looks that the str += is really close to the O(n^2) worst case performance, but it looks more like the other method increases in a perhaps linear scale? I don't know but I think this is enough text I hope.''']

    for string in strings:
        print("String of len:", len(string), "took:", test(listcat, 1000000, string), test(strcat, 1000000, string), "seconds")

testall()
6
Wayne Werner

기존 답변은 매우 잘 작성되고 연구되었지만 여기에 Python 3.6 시대에 대한 또 다른 답변이 있습니다. 지금부터 우리는 literal string interpolation (AKA, f- 문자열) :

>>> import timeit
>>> timeit.timeit('f\'{"a"}{"b"}{"c"}\'', number=1000000)
0.14618930302094668
>>> timeit.timeit('"".join(["a", "b", "c"])', number=1000000)
0.23334730707574636
>>> timeit.timeit('a = "a"; a += "b"; a += "c"', number=1000000)
0.14985873899422586

테스트는 2.3 GHz의 Intel Core i7이 설치된 2012 Retina MacBook Pro에서 CPython 3.6.5를 사용하여 수행되었습니다.

이것은 공식적인 벤치 마크는 아니지만 f- strings를 사용하는 것이 += 연결; 개선 된 측정 항목이나 제안은 물론 환영합니다.

4
Jules

나는 마지막 답변을 다시 썼다. 주 테스트 된 방식에 대한 의견을 나눌 수 있습니까?

import time

start1 = time.clock()
for x in range (10000000):
    dog1 = ' and '.join(['spam', 'eggs', 'spam', 'spam', 'eggs', 'spam','spam', 'eggs', 'spam', 'spam', 'eggs', 'spam'])

end1 = time.clock()
print("Time to run Joiner = ", end1 - start1, "seconds")


start2 = time.clock()
for x in range (10000000):
    dog2 = 'spam'+' and '+'eggs'+' and '+'spam'+' and '+'spam'+' and '+'eggs'+' and '+'spam'+' and '+'spam'+' and '+'eggs'+' and '+'spam'+' and '+'spam'+' and '+'eggs'+' and '+'spam'

end2 = time.clock()
print("Time to run + = ", end2 - start2, "seconds")

참고 :이 예제는 Python 3.5로 작성되었습니다. 여기서 range ()는 이전 xrange ()와 같은 역할을합니다.

내가 얻은 출력 :

Time to run Joiner =  27.086106206103153 seconds
Time to run + =  69.79100515996426 seconds

개인적으로 나는 더 깨끗하고 읽기 쉽기 때문에 'Plusser way'보다 ''.join ([])을 선호합니다.

0
Gerard Kool

이것은 바보 같은 프로그램이 테스트하도록 설계된 것입니다 :)

플러스 사용

import time

if __== '__main__':
    start = time.clock()
    for x in range (1, 10000000):
        dog = "a" + "b"

    end = time.clock()
    print "Time to run Plusser = ", end - start, "seconds"

출력 :

Time to run Plusser =  1.16350010965 seconds

지금 가입하세요 ....

import time
if __== '__main__':
    start = time.clock()
    for x in range (1, 10000000):
        dog = "a".join("b")

    end = time.clock()
    print "Time to run Joiner = ", end - start, "seconds"

출력 :

Time to run Joiner =  21.3877386651 seconds

따라서 python 2.6 Windows의 경우 2.6은 +가 join보다 약 18 배 빠릅니다.)

0
bwawok