отличный вопрос! я сам недавно упал в эту кроличью нору.
Ответ
@ dan04 вдохновил меня расширить его до подкласса unicode
, который обеспечивает согласованное индексирование, нарезку и len()
как для узких, так и для широких сборок Python 2:
class WideUnicode(unicode):
"""String class with consistent indexing, slicing, len() on both narrow and wide Python."""
def __init__(self, *args, **kwargs):
super(WideUnicode, self).__init__(*args, **kwargs)
# use UTF-32LE to avoid a byte order marker at the beginning of the string
self.__utf32le = unicode(self).encode('utf-32le')
def __len__(self):
return len(self.__utf32le) / 4
def __getitem__(self, key):
length = len(self)
if isinstance(key, int):
if key >= length:
raise IndexError()
key = slice(key, key + 1)
if key.stop is None:
key.stop = length
assert key.step is None
return WideUnicode(self.__utf32le[key.start * 4:key.stop * 4]
.decode('utf-32le'))
def __getslice__(self, i, j):
return self.__getitem__(slice(i, j))
с открытым исходным кодом здесь , общественное достояние. пример использования:
text = WideUnicode(obj.text)
for tag in obj.tags:
text = WideUnicode(text[:start] + tag.text + text[end:])
( упрощено от этого использования. )
спасибо @ dan04!