Keďže Python's string
sa nedá'zmeniť, zaujímalo by ma, ako efektívnejšie spojiť reťazec?
Môžem to napísať takto:
s += stringfromelsewhere
alebo takto:
s = []
s.append(somestring)
later
s = ''.join(s)
Pri písaní tejto otázky som našiel dobrý článok, ktorý hovorí o tejto téme.
http://www.skymind.com/~ocrow/python_string/
Ale je to v Pythone 2.x., takže otázka by bola, či sa niečo zmenilo v Pythone 3?
Ak spájate veľa hodnôt, potom ani to. Pridávanie zoznamu je nákladné. Na to môžete použiť StringIO. Najmä ak ho vytvárate v priebehu mnohých operácií.
from cStringIO import StringIO
# python3: from io import StringIO
buf = StringIO()
buf.write('foo')
buf.write('foo')
buf.write('foo')
buf.getvalue()
# 'foofoofoo'
Ak už máte kompletný zoznam vrátený z nejakej inej operácie, potom stačí použiť ''.join(aList)
Z python FAQ: Aký je najefektívnejší spôsob spájania mnohých reťazcov?
objekty str a bytes sú nemenné, preto spojenie mnohých reťazcov dohromady je neefektívne, pretože každé spojenie vytvára nový reťazec. objekt. Vo všeobecnom prípade sú celkové náklady na beh kvadratické v celkovej dĺžke reťazca.
Ak chcete nahromadiť veľa objektov string, odporúčaným idiomom je umiestniť ich do zoznamu a na konci zavolať str.join():
chunks = [] for s in my_strings: chunks.append(s) result = ''.join(chunks)
(iným pomerne efektívnym idiomom je použitie io.StringIO)
Ak chcete hromadiť veľa bajtových objektov, odporúčaným idiomom je rozšíriť bytearray objekt pomocou konkatenácie na mieste (operátor +=):
result = bytearray() for b in my_bytes_objects: result += b
Edit: Bol som hlúpy a výsledky som vložil opačne, aby to vyzeralo, že pridávanie do zoznamu je rýchlejšie ako cStringIO. Pridal som aj testy pre bytearray/str concat, ako aj druhé kolo testov s použitím väčšieho zoznamu s väčšími reťazcami. (Python 2.7.3)
príklad testu v jazyku Python pre veľké zoznamy reťazcov
try:
from cStringIO import StringIO
except:
from io import StringIO
source = ['foo']*1000
%%timeit buf = StringIO()
for i in source:
buf.write(i)
final = buf.getvalue()
# 1000 loops, best of 3: 1.27 ms per loop
%%timeit out = []
for i in source:
out.append(i)
final = ''.join(out)
# 1000 loops, best of 3: 9.89 ms per loop
%%timeit out = bytearray()
for i in source:
out += i
# 10000 loops, best of 3: 98.5 µs per loop
%%timeit out = ""
for i in source:
out += i
# 10000 loops, best of 3: 161 µs per loop
## Repeat the tests with a larger list, containing
## strings that are bigger than the small string caching
## done by the Python
source = ['foo']*1000
# cStringIO
# 10 loops, best of 3: 19.2 ms per loop
# list append and join
# 100 loops, best of 3: 144 ms per loop
# bytearray() +=
# 100 loops, best of 3: 3.8 ms per loop
# str() +=
# 100 loops, best of 3: 5.11 ms per loop
Hoci je to trochu zastarané, Code Like a Pythonista: Idiomatic Python odporúča join()
namiesto +
v tejto časti. Rovnako ako PythonSpeedPerformanceTips vo svojej časti o spájaní reťazcov s nasledujúcou výhradou:
Presnosť tejto časti je sporná vzhľadom na neskoršie verzií jazyka Python. V CPythone 2.5 je spájanie reťazcov pomerne rýchla, aj keď to nemusí platiť rovnako pre iné jazyky Python implementácie. Diskusiu nájdete v časti ConcatenationTestCode.