Classe stringa Python come StringBuilder in C #?


Risposte:


102

Non esiste una correlazione uno a uno. Per un articolo davvero valido, vedere Concatenazione efficiente di stringhe in Python :

La creazione di stringhe lunghe nel linguaggio di programmazione Python a volte può provocare un codice in esecuzione molto lento. In questo articolo indago sulle prestazioni di calcolo di vari metodi di concatenazione di stringhe.


27
Nota che questo articolo è stato scritto sulla base di Python 2.2. I test verrebbero probabilmente in modo un po 'diverso in una versione moderna di Python (CPython di solito ottimizza con successo la concatenazione, ma non vuoi dipendere da questo in un codice importante) e un'espressione del generatore in cui usa una comprensione di elenchi sarebbe degna di considerazione .
Mike Graham

4
Sarebbe bene inserire alcuni punti salienti in quell'articolo, almeno un paio di implementazioni (per evitare problemi di link rot).
jpmc26

3
Metodo 1: resultString + = appendString è il più veloce secondo i test di @ Antoine-tran di seguito
Justas

5
La tua citazione non risponde affatto alla domanda. Si prega di includere le parti pertinenti nella risposta stessa, per conformarsi alle nuove linee guida.
Finanzia la causa di Monica il

27

Ho usato il codice di Oliver Crow (collegamento fornito da Andrew Hare) e l'ho adattato un po 'per adattare Python 2.7.3. (utilizzando il pacchetto timeit). Ho eseguito sul mio personal computer, Lenovo T61, 6 GB di RAM, Debian GNU / Linux 6.0.6 (squeeze).

Ecco il risultato per 10.000 iterazioni:

metodo1: 0,0538418292999 sec
dimensione del processo 4800 kb
method2: 0.22602891922 sec
dimensione del processo 4960 kb
metodo3: 0,0605459213257 secondi
dimensione del processo 4980 kb
method4: 0.0544030666351 sec
dimensione del processo 5536 kb
metodo5: 0,0551080703735 sec
dimensione del processo 5272 kb
method6: 0.0542731285095 sec
dimensione del processo 5512 kb

e per 5.000.000 di iterazioni (il metodo 2 è stato ignorato perché funzionava troppo lentamente, come per sempre):

method1: 5.88603997231 sec
dimensione del processo 37976 kb
method3: 8.40748500824 sec
dimensione del processo 38024 kb
method4: 7,96380496025 sec
dimensione del processo 321968 kb
method5: 8.03666186333 sec
dimensione del processo 71720 kb
method6: 6.68192911148 sec
dimensione del processo 38240 kb

È abbastanza ovvio che i ragazzi di Python hanno fatto un ottimo lavoro per ottimizzare la concatenazione di stringhe, e come ha detto Hoare: "l'ottimizzazione prematura è la radice di tutti i mali" :-)


2
Apparentemente Hoare non accetta che: hans.gerwitz.com/2004/08/12/…
Pimin Konstantin Kefaloukos

5
Non è un'ottimizzazione prematura evitare fragili ottimizzazioni dipendenti dall'interprete. Se mai desideri eseguire il porting su PyPy o rischiare di incappare in uno dei tanti casi di errore sottile per l'ottimizzazione, fai le cose nel modo giusto.
Veedrac

1
Sembra che il metodo 1 sia più facile da ottimizzare per il compilatore.
mbomb007

25

Affidarsi alle ottimizzazioni del compilatore è fragile. I parametri di riferimento collegati nella risposta accettata e i numeri forniti da Antoine-tran non sono affidabili. Andrew Hare commette l'errore di includere una chiamata arepr nei suoi metodi. Ciò rallenta tutti i metodi allo stesso modo, ma oscura la vera penalità nella costruzione della stringa.

Usa join. È molto veloce e più robusto.

$ ipython3
Python 3.5.1 (default, Mar  2 2016, 03:38:02) 
IPython 4.1.2 -- An enhanced Interactive Python.

In [1]: values = [str(num) for num in range(int(1e3))]

In [2]: %%timeit
   ...: ''.join(values)
   ...: 
100000 loops, best of 3: 7.37 µs per loop

In [3]: %%timeit
   ...: result = ''
   ...: for value in values:
   ...:     result += value
   ...: 
10000 loops, best of 3: 82.8 µs per loop

In [4]: import io

In [5]: %%timeit
   ...: writer = io.StringIO()
   ...: for value in values:
   ...:     writer.write(value)
   ...: writer.getvalue()
   ...: 
10000 loops, best of 3: 81.8 µs per loop

Sì, la reprchiamata domina il runtime, ma non è necessario rendere l'errore personale.
Alex Reinking

3
@AlexReinking mi dispiace, niente di personale significava. Non sono sicuro di cosa ti abbia fatto pensare che fosse personale. Ma se era l'uso dei loro nomi, li ho usati solo per fare riferimento alle risposte dell'utente (corrisponde ai nomi utente, non sono sicuro se ci sia un modo migliore).
GrantJ

1
buon esempio di tempismo che separa l'inizializzazione dei dati e le operazioni di concatenazione
aiodintsov

19

Python ha diverse cose che soddisfano scopi simili:

  • Un modo comune per costruire stringhe di grandi dimensioni da pezzi è aumentare un elenco di stringhe e unirle quando hai finito. Questo è un idioma Python usato di frequente.
    • Per creare stringhe che incorporano dati con la formattazione, dovresti eseguire la formattazione separatamente.
  • Per l'inserimento e la cancellazione a livello di carattere, manterrai un elenco di stringhe di lunghezza uno. (Per fare questo da una stringa, dovresti chiamare list(your_string). Puoi anche usare un UserString.MutableStringper questo.
  • (c)StringIO.StringIO è utile per cose che altrimenti richiederebbero un file, ma meno per la costruzione di stringhe generale.

10

Usando il metodo 5 dall'alto (The Pseudo File) possiamo ottenere ottime prestazioni e flessibilità

from cStringIO import StringIO

class StringBuilder:
     _file_str = None

     def __init__(self):
         self._file_str = StringIO()

     def Append(self, str):
         self._file_str.write(str)

     def __str__(self):
         return self._file_str.getvalue()

ora lo uso

sb = StringBuilder()

sb.Append("Hello\n")
sb.Append("World")

print sb


-1

Non c'è un analogo esplicito - penso che dovresti usare concatenazioni di stringhe (probabilmente ottimizzate come detto prima) o classi di terze parti (dubito che siano molto più efficienti - gli elenchi in python sono di tipo dinamico, quindi non funziona velocemente char [] per buffer come presumo). Le classi simili a Stringbuilder non sono un'ottimizzazione prematura a causa della caratteristica innata delle stringhe in molti linguaggi (immutabilità), che consente molte ottimizzazioni (ad esempio, facendo riferimento allo stesso buffer per slice / sottostringhe). Le classi Stringbuilder / stringbuffer / stringstream funzionano molto più velocemente della concatenazione di stringhe (producendo molti piccoli oggetti temporanei che necessitano ancora di allocazioni e garbage collection) e persino di strumenti simili a printf per la formattazione di stringhe, senza la necessità di interpretare l'overhead del pattern di formattazione che è piuttosto faticoso per molte chiamate di formato.


-4

Nel caso in cui stai cercando un metodo di concatenazione di stringhe veloce in Python, non hai bisogno di una classe StringBuilder speciale. La concatenazione semplice funziona altrettanto bene senza la penalizzazione delle prestazioni vista in C #.

resultString = ""

resultString += "Append 1"
resultString += "Append 2"

Vedi la risposta di Antoine-tran per i risultati delle prestazioni

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.