Kadangi Python's string
negali'būti pakeista, man buvo įdomu, kaip efektyviau sujungti eilutę?
Galiu parašyti taip:
s += stringfromelsewhere
arba taip:
s = []
s.append(somestring)
later
s = ''.join(s)
Rašydamas šį klausimą radau gerą straipsnį, kuriame kalbama šia tema.
http://www.skymind.com/~ocrow/python_string/
Tačiau jis skirtas Python 2.x., todėl klausimas būtų toks: ar kažkas pasikeitė Python 3?
Jei sujungiate daug reikšmių, tuomet nei viena iš jų. Sąrašo pridėjimas yra brangus. Tam galite naudoti StringIO. Ypač jei jį sudarote per daug operacijų.
from cStringIO import StringIO
# python3: from io import StringIO
buf = StringIO()
buf.write('foo')
buf.write('foo')
buf.write('foo')
buf.getvalue()
# 'foofoofoo'
Jei jau turite visą sąrašą, grąžintą atlikus kitą operaciją, tiesiog naudokite ''.join(aList)
Iš Python DUK: Koks yra efektyviausias būdas sujungti daugybę eilučių?.
str ir bytes objektai yra nekintami, todėl daugelio objektų sujungimas eilučių yra neefektyvu, nes kiekvienas sujungimas sukuria naują eilutę. objektą. Bendruoju atveju bendros vykdymo laiko sąnaudos yra kvadratinės bendras eilutės ilgis.
Norint sukaupti daug str objektų, rekomenduojama juos patalpinti į sąrašą ir pabaigoje iškviesti str.join():
chunks = [] for s in my_strings: chunks.append(s) rezultatas = ''.join(chunks)
(kita pakankamai efektyvi idioma - naudoti io.StringIO)
Norint sukaupti daug baitų objektų, rekomenduojama idioma yra išplėsti baitų masyvo objektą, naudojant jungimą vietoje (operatorius +=):
rezultatas = bytearray() for b in my_bytes_objects: result += b
Edit: buvau kvailas ir rezultatus įklijavau atvirkščiai, todėl atrodė, kad įrašymas į sąrašą buvo greitesnis nei cStringIO. Taip pat pridėjau bytearray/str concat testus, taip pat antrą testų ratą, kuriame naudojamas didesnis sąrašas su didesnėmis eilutėmis. (Python 2.7.3)
ipython testų pavyzdys dideliems stygų sąrašams
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
Nors ir šiek tiek pasenęs, Code Like a Pythonista: Idiomatic Python rekomenduoja join()
, o ne +
šiame skyriuje. Kaip ir PythonSpeedPerformanceTips skyriuje apie eilučių gretinimą, su šia išlyga:
Šio skyriaus tikslumas ginčijamas dėl vėlesnių Python versijų. CPython 2.5 versijoje eilučių gretinimas yra gana greitas, nors tai gali būti netaikoma ir kitose Python realizacijoms. Apie tai skaitykite ConcatenationTestCode.