python - examples - seaborn
Cuerdas mutables en Python (4)
Por favor, ¿sabe de una biblioteca de Python que proporcione cadenas mutables? Google volvió 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.
Edit: Gracias por las respuestas, pero estoy después de una biblioteca eficiente . Es decir, ''''.join(list)
podría funcionar pero esperaba algo más optimizado. Además, tiene que admitir las funciones habituales de las cadenas normales, como expresiones regulares y Unicode.
¿Qué tal si simplemente sub-clasificamos la list
(el primer ejemplo de 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 es trivial, 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'']
Lo siguiente está arreglado, ver actualización a continuación.
Hay una advertencia (solucionable): no hay verificación (aún) de que cada elemento sea de hecho un personaje. Al menos fallará la impresión para todo menos cadenas. Sin embargo, se pueden unir y causar situaciones extrañas como esta: [ver el ejemplo de código a continuación]
Con el __setitem__
personalizado, asignar una cadena de longitud! = 1 a un elemento CharList generará un ValueError
. Todo lo demás aún puede asignarse libremente, pero generará 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, se pueden agregar más cheques fácilmente (potencialmente también a __setslice__
o cambiando la clase base a collections.Sequence
__setslice__
(el rendimiento podría ser diferente ?!), consulte 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'']
En Python el tipo de secuencia mutable es bytearray ver este enlace
Esto te permitirá cambiar los caracteres de manera eficiente en una cadena. Aunque no puedes cambiar la longitud de la cuerda.
>>> 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''>)
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 puede subclase StringIO, búfer o bytearray.