2012-05-13 25 views
24

Por favor, ¿sabe de una biblioteca Python que proporciona cadenas mutables? Google arrojó sorprendentemente pocos resultados. La única biblioteca utilizable que encontré es http://code.google.com/p/gapbuffer/ que está en C, pero preferiría que estuviera escrita en Python puro.Cadenas mutables en Python

Editar: Gracias por las respuestas, pero estoy buscando una biblioteca eficiente. Es decir, ''.join(list) podría funcionar, pero esperaba algo más optimizado. Además, tiene que admitir las cosas habituales que hacen las cadenas regulares, como regex y unicode.

+5

listas de trabajo bastante bien para este propósito. –

+0

Un par de enlaces: [LINK1] (http://mail.python.org/pipermail/tutor/2003-August/024485.html), [LINK2] (http://www.skymind.com/~ocrow/ python_string /) – digEmAll

+4

¿Puedes explicar por qué necesitas cadenas mutables? ¿Cuál es el caso de uso? –

Respuesta

19

En Python mutable tipo de secuencia es bytearray ver this link

+2

Los almacenamientos intermedios son de solo lectura. – Marcin

+1

Gracias Marcin, muestra la frecuencia con la que uso los búferes ... –

+0

No estoy seguro de a qué se refiere @Marcin porque bytearrays le permite asignar un nuevo valor a una porción del bytearray. – jonathanrocher

11
class MutableString(object): 
    def __init__(self, data): 
     self.data = list(data) 
    def __repr__(self): 
     return "".join(self.data) 
    def __setitem__(self, index, value): 
     self.data[index] = value 
    def __getitem__(self, index): 
     if type(index) == slice: 
      return "".join(self.data[index]) 
     return self.data[index] 
    def __delitem__(self, index): 
     del self.data[index] 
    def __add__(self, other): 
     self.data.extend(list(other)) 
    def __len__(self): 
     return len(self.data) 

... y así sucesivamente, y así sucesivamente.

También podría establecer la subclase StringIO, buffer o bytearray.

+0

Para poder utilizar los métodos de expresiones regulares y de cadena como 'encontrar', debe hacer una subclase de' str' en lugar de 'object'. –

+0

Corrección: expresiones regulares y 'buscar' solo funcionan en la cadena original. Las modificaciones hechas a través de '__setitem__' son ignoradas. ¿Hay alguna forma de usar regex en MutableStrings? –

+0

Puede hacer 're.match (expresión, repr (cadena_mutable))' –

15

Esto le permitirá cambiar de manera eficiente los caracteres en una cadena. Aunque no puedes cambiar la longitud de la cadena.

>>> import ctypes 

>>> a = 'abcdefghijklmn' 
>>> mutable = ctypes.create_string_buffer(a) 
>>> mutable[5:10] = ''.join(reversed(list(mutable[5:10].upper()))) 
>>> a = mutable.value 
>>> print `a, type(a)` 
('abcdeJIHGFklmn', <type 'str'>) 
+2

** TENGA EN CUENTA ** que el buffer incluye el terminador en su 'len()' reportado. ** Esto cortará rebanadas con índices negativos ** a menos que agregue un '-1 adicional a cada índice negativo. (Para búferes Unicode, también es '-1 ', porque' len' y los índices de corte para estos tipos están en caracteres.) –

1

¿Qué hay de simplemente subclasificar list (el principal ejemplo de la mutabilidad en Python)?

class CharList(list): 

    def __init__(self, s): 
     list.__init__(self, s) 

    @property 
    def list(self): 
     return list(self) 

    @property 
    def string(self): 
     return "".join(self) 

    def __setitem__(self, key, value): 
     if isinstance(key, int) and len(value) != 1: 
      cls = type(self).__name__ 
      raise ValueError("attempt to assign sequence of size {} to {} item of size 1".format(len(value), cls)) 
     super(CharList, self).__setitem__(key, value) 

    def __str__(self): 
     return self.string 

    def __repr__(self): 
     cls = type(self).__name__ 
     return "{}(\'{}\')".format(cls, self.string) 

Esto solo une la lista a una cadena si desea imprimirla o solicitar activamente la representación de la cadena. Mutar y extender son triviales, y el usuario ya sabe cómo hacerlo, ya que es solo una lista.

Ejemplo de uso:

s = "te_st" 
c = CharList(s) 
c[1:3] = "oa" 
c += "er" 
print C# prints "toaster" 
print c.list # prints ['t', 'o', 'a', 's', 't', 'e', 'r'] 

está fijado el siguiente, véase la actualización a continuación.

Hay una advertencia (que se puede solucionar): no hay ningún control (todavía) de que cada elemento sea de hecho un carácter. Por lo menos fallará la impresión para todo menos para cadenas. Sin embargo, aquellos que se pueden unir y puede causar situaciones extrañas como esta: [véase el ejemplo de código siguiente]

Con la costumbre __setitem__, la asignación de una cadena de longitud = 1 a un elemento de CharList elevará un ValueError!. Todo lo demás se puede asignar libremente, pero aumentará un TypeError: sequence item n: expected string, X found al imprimir, debido a la operación string.join(). Si eso no es lo suficientemente bueno, más controles pueden ser fácilmente añadidos (potencialmente también para __setslice__ o cambiando la clase base a collections.Sequence (rendimiento puede ser diferente ?!), cf. here)

s = "test" 
c = CharList(s) 
c[1] = "oa" 
# with custom __setitem__ a ValueError is raised here! 
# without custom __setitem__, we could go on: 
c += "er" 
print C# prints "toaster" 
# this looks right until here, but: 
print c.list # prints ['t', 'oa', 's', 't', 'e', 'r']