2012-05-13 38 views
24

Xin vui lòng, bạn có biết thư viện Python cung cấp chuỗi có thể thay đổi được không? Google đã trả về một vài kết quả đáng ngạc nhiên. Các thư viện có thể sử dụng duy nhất tôi tìm thấy là http://code.google.com/p/gapbuffer/ đó là trong C nhưng tôi muốn nó được viết bằng Python tinh khiết.Chuỗi có thể thay đổi trong Python

Chỉnh sửa: Cảm ơn bạn đã trả lời nhưng tôi theo sau thư viện hiệu quả. Tức là, ''.join(list) có thể hoạt động nhưng tôi đã hy vọng điều gì đó được tối ưu hóa hơn. Ngoài ra, nó có để hỗ trợ các công cụ thông thường chuỗi làm, như regex và unicode.

+5

Chức năng hoạt động khá tốt cho việc này mục đích. –

+0

Một vài liên kết: [LINK1] (http://mail.python.org/pipermail/tutor/2003-August/024485.html), [LINK2] (http://www.skymind.com/~ocrow/ python_string /) – digEmAll

+4

Bạn có thể giải thích, tại sao bạn cần chuỗi có thể thay đổi? Trường hợp sử dụng là gì? –

Trả lời

19

Trong Python có thể thay đổi kiểu chuỗi là bytearray thấy this link

+2

Bộ đệm chỉ đọc. – Marcin

+1

Cảm ơn Marcin, cho biết mức độ thường xuyên tôi sử dụng bộ đệm ... –

+0

Tôi không chắc chắn về những gì @Marcin đề cập đến vì các phép thuật tạm thời cho phép bạn gán một giá trị mới cho một lát của dấu thăng. – 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) 

... và vân vân, và vân vân.

Bạn cũng có thể phân lớp StringIO, bộ đệm hoặc bytearray.

+0

Để có thể sử dụng các phương thức chuỗi và regex như 'find', bạn cần phải phân lớp từ' str' thay vì 'object'. –

+0

Hiệu chỉnh: regex và 'find' chỉ hoạt động trên chuỗi gốc. Các sửa đổi được thực hiện thông qua '__setitem__'are bị bỏ qua. Có cách nào để sử dụng regex trên MutableStrings? –

+0

Bạn có thể làm 're.match (biểu thức, repr (mutable_string))' –

15

Điều này sẽ cho phép bạn thay đổi hiệu quả các ký tự trong chuỗi. Mặc dù bạn không thể thay đổi độ dài chuỗi.

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

** ĐƯỢC CẢNH BÁO ** rằng bộ đệm bao gồm trình kết thúc vào báo cáo 'len()' của nó. ** Điều này sẽ phá vỡ các lát với các chỉ số âm ** trừ khi bạn thêm một '-1' phụ vào mỗi chỉ số âm. (Đối với các bộ đệm unicode, nó cũng là '-1', bởi vì' len' và các chỉ mục slice cho các kiểu này là các ký tự.) –

1

Làm thế nào để phân lớp đơn giản là list (ví dụ chính về khả năng thay đổi trong 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) 

Chỉ tham gia danh sách quay lại chuỗi nếu bạn muốn in hoặc chủ động yêu cầu biểu diễn chuỗi. Việc thay đổi và mở rộng là không đáng kể và người dùng biết cách thực hiện nó vì đó chỉ là danh sách.

sử dụng Ví dụ:

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

Sau đây là cố định, xem cập nhật dưới đây.

Có một (solvable) caveat: Không có kiểm tra (chưa) rằng mỗi phần tử thực sự là một nhân vật. Nó sẽ ít nhất là thất bại in ấn cho tất cả mọi thứ nhưng dây. Tuy nhiên, những người có thể tham gia và có thể gây ra những tình huống kỳ lạ như thế này: [xem mã ví dụ dưới đây]

Với tùy chỉnh __setitem__, gán một chuỗi có độ dài = 1 tới một mục CharList sẽ nâng cao một ValueError!. Mọi thứ khác vẫn có thể được gán tự do nhưng sẽ tăng TypeError: sequence item n: expected string, X found khi in, do hoạt động string.join(). Nếu đó là không đủ tốt, kiểm tra hơn nữa có thể được thêm vào một cách dễ dàng (có khả năng còn __setslice__ hoặc bằng cách chuyển các lớp cơ sở để collections.Sequence (hiệu suất có thể khác ?!), xem 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'] 
Các vấn đề liên quan