icono
¿Hay alguna clase de cadena en Python como StringBuilder
Cía#?
Andrés Liebre
No hay una correlación uno a uno. Para un artículo realmente bueno por favor vea Concatenación eficiente de cadenas en Python:
La construcción de cadenas largas en el lenguaje de programación Python a veces puede resultar en un código de ejecución muy lento. En este artículo investigo el rendimiento computacional de varios métodos de concatenación de cadenas.
TLDR el método más rápido está a continuación. Es extremadamente compacto, y también bastante comprensible:
def method6():
return ''.join([`num` for num in xrange(loop_count)])
-
Tenga en cuenta que este artículo fue escrito en base a Python 2.2. Es probable que las pruebas resulten algo diferentes en una versión moderna de Python (CPython generalmente optimiza con éxito la concatenación, pero no desea depender de esto en código importante) y una expresión de generador donde usa una comprensión de lista sería digna de consideración .
–Mike Graham
10 de marzo de 2010 a las 6:35
-
Sería bueno incluir algunos aspectos destacados en ese artículo, al menos un par de implementaciones (para evitar problemas de enlaces rotos).
– jpmc26
29 de julio de 2014 a las 22:22
-
Método 1: resultString += appendString es el más rápido según las pruebas de @Antoine-tran a continuación
– Tal como
31 de diciembre de 2015 a las 17:47
-
Su cita no responde en absoluto a la pregunta. Incluya las partes relevantes en su propia respuesta, para cumplir con las nuevas pautas.
– Nic
21 oct 2016 a las 16:48
Confiar en las optimizaciones del compilador es frágil. No se puede confiar en los puntos de referencia vinculados en la respuesta aceptada y los números proporcionados por Antoine-tran. Andrew Hare comete el error de incluir una llamada a repr
en sus métodos. Eso ralentiza todos los métodos por igual pero oscurece la pena real en la construcción de la cadena.
Usar join
. Es muy rápido y más 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í el
repr
call domina el tiempo de ejecución, pero no hay necesidad de hacer el error personal.– Alex Reining
17 de agosto de 2018 a las 21:43
-
@AlexReinking lo siento, no significa nada personal. No estoy seguro de qué te hizo pensar que era personal. Pero si fue el uso de sus nombres, los usé solo para referirme a las respuestas del usuario (coincide con los nombres de usuario, no estoy seguro de si hay una mejor manera).
– GrantJ
18 de agosto de 2018 a las 19:15
-
buen ejemplo de sincronización que separa las operaciones de inicialización y concatenación de datos
– aiodintsov
29 de junio de 2019 a las 22:37
He usado el código de Oliver Crow (enlace proporcionado por Andrew Hare) y lo he adaptado un poco para personalizar Python 2.7.3. (usando el paquete timeit). Corrí en mi computadora personal, Lenovo T61, 6 GB de RAM, Debian GNU/Linux 6.0.6 (squeeze).
Aquí está el resultado de 10.000 iteraciones:
method1: 0.0538418292999 secs process size 4800 kb method2: 0.22602891922 secs process size 4960 kb method3: 0.0605459213257 secs process size 4980 kb method4: 0.0544030666351 secs process size 5536 kb method5: 0.0551080703735 secs process size 5272 kb method6: 0.0542731285095 secs process size 5512 kb
y para 5,000,000 de iteraciones (se ignoró el método 2 porque funcionó demasiado lento, como una eternidad):
method1: 5.88603997231 secs process size 37976 kb method3: 8.40748500824 secs process size 38024 kb method4: 7.96380496025 secs process size 321968 kb method5: 8.03666186333 secs process size 71720 kb method6: 6.68192911148 secs process size 38240 kb
Es bastante obvio que los chicos de Python han hecho un gran trabajo para optimizar la concatenación de cadenas y, como dijo Hoare: “la optimización prematura es la raíz de todos los males” 🙂
-
Aparentemente, Hoare no acepta que: hans.gerwitz.com/2004/08/12/…
– Pimín Konstantin Kefaloukos
11 de diciembre de 2012 a las 13:13
-
No es una optimización prematura para evitar optimizaciones frágiles y dependientes del intérprete. Si alguna vez desea migrar a PyPy o arriesgarse a encontrar uno de los muchos casos de fallas sutiles para la optimización, haga las cosas de la manera correcta.
– Veedrac
3 de noviembre de 2014 a las 21:46
-
Parece que el Método 1 es más fácil de optimizar para el compilador.
– bombomb007
29 de abril de 2015 a las 18:21
mike graham
Python tiene varias cosas que cumplen propósitos similares:
- Una forma común de construir cadenas grandes a partir de piezas es hacer crecer una lista de cadenas y unirlas cuando haya terminado. Este es un modismo de Python de uso frecuente.
- Para crear cadenas que incorporen datos con formato, haría el formato por separado.
- Para la inserción y eliminación a nivel de carácter, mantendría una lista de cadenas de longitud uno. (Para hacer esto a partir de una cadena, llamarías
list(your_string)
. También podrías usar unUserString.MutableString
para esto. (c)StringIO.StringIO
es útil para cosas que de otro modo tomarían un archivo, pero menos para la construcción general de cadenas.
Usando el método 5 de arriba (The Pseudo File) podemos obtener muy buen rendimiento y flexibilidad
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()
ahora usándolo
sb = StringBuilder()
sb.Append("Hello\n")
sb.Append("World")
print sb
dominic k
Cerebro
No hay un análogo explícito: creo que se espera que use concatenaciones de cadenas (probablemente optimizadas como se dijo antes) o una clase de terceros (dudo que sean mucho más eficientes: las listas en python son de tipo dinámico, por lo que no funcionan rápido) carbonizarse[] para el búfer como supongo). Las clases similares a Stringbuilder no son una optimización prematura debido a la característica innata de las cadenas en muchos idiomas (inmutabilidad), que permite muchas optimizaciones (por ejemplo, hacer referencia al mismo búfer para segmentos/subcadenas). Las clases similares a Stringbuilder/stringbuffer/stringstream funcionan mucho más rápido que concatenar cadenas (produciendo muchos objetos temporales pequeños que aún necesitan asignaciones y recolección de basura) e incluso herramientas de formato de cadena similares a printf, sin necesidad de interpretar la sobrecarga del patrón de formato que consume bastante para muchas llamadas de formato.
Este es un duplicado del equivalente Python de Java StringBuffer. PRECAUCIÓN: Las respuestas aquí están muy desactualizadas y, de hecho, se han vuelto engañosas. Consulte esa otra pregunta para obtener respuestas que son más relevantes para las versiones modernas de Python (ciertamente 2.7 y superiores).
– Jean-François Corbett
20 de noviembre de 2017 a las 8:52