2012-05-13 1 views
24

Возможно, вы знаете о библиотеке Python, которая предоставляет изменяемые строки? Google вернул на удивление мало результатов. Единственная используемая библиотека, которую я нашел, - http://code.google.com/p/gapbuffer/, которая находится в C, но я бы предпочел, чтобы она была написана на чистом Python.Mutable строки в Python

Редактировать: Спасибо за ответы, но я после эффективный библиотека. То есть ''.join(list) может работать, но я надеялся на что-то более оптимизированное. Кроме того, он должен поддерживать обычные обычные строки, например regex и unicode.

+5

Списки работают довольно хорошо для этого цель. –

+0

Несколько ссылок: [LINK1] (http://mail.python.org/pipermail/tutor/2003-August/024485.html), [LINK2] (http://www.skymind.com/~ocrow/ python_string /) – digEmAll

+4

Можете ли вы объяснить, почему вам нужны изменяемые строки? Что такое прецедент? –

ответ

19

В Python изменяемый тип порядковом ByteArray см this link

+2

Буферы считываются только. – Marcin

+1

Спасибо Marcin, показывает, как часто я использую буферы ... –

+0

Я не уверен, что означает @Marcin, потому что bytearrays позволяет назначить новое значение фрагменту 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) 

... и так далее, и так далее.

Вы также можете подклассифицировать StringIO, buffer или bytearray.

+0

Чтобы использовать регулярные и строковые методы, такие как 'find', вам нужно подклассом из' str' вместо 'object'. –

+0

Исправление: регулярное выражение и 'find' работают только с исходной строкой. Изменения, сделанные с помощью '__setitem__', не учитываются. Есть ли способ использовать регулярное выражение для MutableStrings? –

+0

Вы можете сделать 're.match (выражение, repr (mutable_string))' –

15

Это позволит вам эффективно изменять символы в строке. Хотя вы не можете изменить длину строки.

>>> 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

** BE WARNED **, что буфер включает терминатор в его сообщенный 'len()'. ** Это сломает срезы с отрицательными индексами **, если вы не добавите лишний «-1» к каждому отрицательному индексу. (Для буферов в Юникоде это тоже '-1', потому что индексы' len' и slice для этих типов находятся в символах.) –

1

Как насчет просто к югу от причислять list (главный пример для изменчивости в 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) 

Это только соединение с списком возвращается к строке, если вы хотите распечатать ее или активно запросить представление строки. Мутирование и расширение тривиально, и пользователь знает, как это сделать, поскольку это всего лишь список.

Пример использования:

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'] 

Ниже фиксируется, см обновление ниже.

Существует одно (разрешимое) предостережение: нет проверки (пока), что каждый элемент действительно является символом. По крайней мере, он будет печатать для всех, кроме строк. Тем не менее, те могут быть соединены и может вызвать странные ситуации, как это: [смотри пример кода ниже]

С обычаем __setitem__, назначая строку длины = 1 к пункту CharList поднимет ValueError!. Все остальное все еще можно свободно назначить, но при печати будет поднять TypeError: sequence item n: expected string, X found в связи с операцией string.join(). Если этого не достаточно, дополнительные проверки могут быть легко добавлены (потенциально также __setslice__ или переключая базовый класс для collections.Sequence (производительность может отличаться ?!), ср 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'] 

 Смежные вопросы

  • Нет связанных вопросов^_^