модификация строк в Python - PullRequest
19 голосов
/ 12 августа 2010

В Python строки неизменны.

Какова стандартная идиома для обхода строки за символом и ее изменения?

Единственные методы, которые я могу придумать, - это некоторые действительно вонючие хаки, связанные с объединением в результирующую строку.

-

В С:

for(int i = 0; i < strlen(s); i++)
{
   s[i] = F(s[i]);
}

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

Ответы [ 13 ]

17 голосов
/ 12 августа 2010

Не используйте строку, используйте что-то изменяемое, например bytearray:

#!/usr/bin/python

s = bytearray("my dog has fleas")
for n in xrange(len(s)):
    s[n] = chr(s[n]).upper()
print s

Результат:

MY DOG HAS FLEAS

Редактировать:

Так как1009 *, вы не (обязательно) работаете с символами .Вы работаете с байтами .Так что это тоже работает:

s = bytearray("\x81\x82\x83")
for n in xrange(len(s)):
    s[n] = s[n] + 1
print repr(s)

дает:

bytearray(b'\x82\x83\x84')

Если вы хотите изменить символы в строке Unicode, возможно, вы захотите работать с memoryview, хотя это не поддерживает Unicode напрямую.

17 голосов
/ 12 августа 2010

Аналог Python вашего C:

for(int i = 0; i < strlen(s); i++)
{
   s[i] = F(s[i]);
}

будет:

s = "".join(F(c) for c in s)

, что также очень выразительно.В нем точно говорится о том, что происходит, но скорее в функциональном, чем в процедурном стиле.

10 голосов
/ 12 августа 2010

вы можете использовать модуль UserString:

 >>> import UserString
... s = UserString.MutableString('Python')
... print s
Python
>>> s[0] = 'c'
>>> print s
cython
7 голосов
/ 12 августа 2010

Я бы сказал, что самый Pythonic способ использовать map():

s = map(func, s) # func has been applied to every character in s

Это эквивалентно написанию:

s = "".join(func(c) for c in s)
3 голосов
/ 12 августа 2010

string.translate, вероятно, самая близкая функция к тому, что вы ищете.

2 голосов
/ 12 августа 2010

Присвоение определенного символа определенному индексу в строке не является особенно распространенной операцией, поэтому, если вам понадобится это сделать, подумайте, может ли быть лучший способ выполнить задачу.Но если вам нужно, вероятно, самый стандартный способ - это преобразовать строку в список, внести изменения и затем преобразовать ее обратно в строку.

s = 'abcdefgh'
l = list(s)
l[3] = 'r'
s2 = ''.join(l)

РЕДАКТИРОВАТЬ: Как указано в ответе bstpierre, bytearray, вероятно, даже лучше для этой задачи, чем list, если вы не работаете со строками Unicode.

s = 'abcdefgh'
b = bytearray(s)
b[3] = 'r'
s2 = str(b)
2 голосов
/ 12 августа 2010

Строки являются итеративными и могут проходить как списки. Строки также имеют ряд базовых методов, таких как .replace(), которые могут быть тем, что вы ищете. Все строковые методы возвращают новую строку. Поэтому вместо того, чтобы изменить строку на месте, вы можете просто заменить ее существующее значение.

>>> mystring = 'robot drama'
>>> mystring = mystring.replace('r', 'g')
>>> mystring
'gobot dgama'
1 голос
/ 23 ноября 2018

Вначале в вопросе говорится, что строки неизменны, а затем запрашивается способ их изменения на месте.Это довольно противоречиво.В любом случае, так как этот вопрос появляется в верхней части списка, когда вы ищете «модификацию строки Python на месте», я добавляю ответ для реального изменения на месте.

Строки кажутся неизменнымикогда вы смотрите на методы класса строки.Но ни один язык с интерфейсом для C не может обеспечить неизменные типы данных.Вопрос только в том, нужно ли вам писать код на C, чтобы добиться желаемой модификации.

Здесь python ctypes - ваш друг.Поскольку он поддерживает получение указателей и включает в себя функции копирования в C-образную память, строку Python можно изменить на месте следующим образом:

s = 16 * "."
print s
ctypes.memmove(ctypes.c_char_p(s), "Replacement", 11)
print s

Результат:

................
Replacement.....

(Конечно, вы можете вычислить замещающую строку во время выполнения, применяя функцию F к каждому символу исходной строки. Различные способы, как это сделать, были показаны в предыдущих ответах.)

Обратите внимание, что я никоим образом не поощряю это делать.Однако мне пришлось написать замену для класса, который был сопоставлен с C ++ на python и включил метод:

int readData(char* data, int length)

(вызывающий должен обеспечить память length байтами, а затем метод записываетдоступные данные - до length - в эту память, возвращающие количество записанных байтов.) Хотя это очень разумный API в C / C ++, его не следует делать доступным в качестве метода класса Python илипо крайней мере, пользователи API должны знать, что они могут передавать только изменяемые байтовые массивы в качестве параметра.

Как и следовало ожидать, «общее использование» метода такое, как показано в моем примере (создайте строку и передайте ее вместе с ее длиной в качестве аргументов).Поскольку я действительно не хотел писать расширение C / C ++, мне пришлось придумать решение для реализации поведения в моем классе замещения с использованием только Python.

1 голос
/ 12 августа 2010

Вот пример использования translate для переключения "-" с "." и прописные буквы "a" s

>>> from string import maketrans
>>> trans_table = maketrans(".-a","-.A")
>>> "foo-bar.".translate(trans_table)
'foo.bAr-'

Это намного эффективнее, чем переход к байтовому массиву и обратно, если вам просто нужно заменить один символ

1 голос
/ 12 августа 2010
>>> mystring = "Th1s 1s my str1ng"
>>> mystring.replace("1", "i")
'This is my string'

Если вы хотите сохранить эту новую строку, вам потребуется mystring = mystring.replace("1", "i").Это потому, что в Python строки являются неизменяемыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...