Python modify string in place

In Python, strings are immutable.

What is the standard idiom to walk through a string character-by-character and modify it?

The only methods I can think of are some genuinely stanky hacks related to joining against a result string.

--

In C:

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

This is super expressive and says exactly what I am doing. That is what I am looking for. 

share improve this question
 
 
I guess since they are immutable you can't "modify it"... do you mean constructing a new string char-by-char?–  Joe Koberg  Aug 12 '10 at 0:02
 
This is really rare. Can you give a context or a use case for doing this? –  S.Lott  Aug 12 '10 at 0:21
 
Adding noise to a message for testing. –  Paul Nathan  Aug 12 '10 at 0:22
 
@Paul Nathan: "Adding noise to a message"? As in "replacing characters at random"? What's wrong with replace for this? –  S.Lott  Aug 12 '10 at 2:43
 
@S.Lott: Replace selects against pre-known elements in the list ``mystring.replace("1", "i")`; whereas I want to iterate by index - I don't know what elements will be in the list per se. (Why does this have to be such a pain?)–  Paul Nathan  Aug 12 '10 at 5:51

12 Answers

active oldest votes
up vote 12 down vote

The Python analog of your C:

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

would be:

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

which is also very expressive. It says exactly what is happening, but in a functional style rather than a procedural style.

share improve this answer
 
 
Interesting; I sort of like it, except for the null string. Probably as good as I'm getting though. –  Paul Nathan Aug 12 '10 at 0:35
1  
A significant part of the C to me is that it works in-place. –  Joe Koberg  Aug 12 '10 at 7:33
 
@Joe Koberg: A significant part of the Python is that it's shorter and more clear. "in place" is limiting because you can't make the string longer. –  S.Lott  Aug 12 '10 at 10:12
 
I understand that, but the OP seemed to be focusing on it. And rejected many standard python string transformation methods. That it didn't work in-place was the only thing left. –  Joe Koberg  Aug 12 '10 at 15:26
 
Isn't map() the same as the list comprehension and join? –  Javier  Aug 12 '10 at 20:53
up vote 11 down vote

Don't use a string, use something mutable like bytearray:

#!/usr/bin/python

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

Results in:

MY DOG HAS FLEAS

Edit:

Since this is a bytearray, you aren't (necessarily) working with characters. You're working with bytes. So this works too:

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

gives:

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

If you want to modify characters in a Unicode string, you'd maybe want to work with memoryview, though that doesn't support Unicode directly.

share improve this answer
 
2  
They aren't Characters, however, just bytes. Works only for ASCII, not Unicode. –  S.Lott  Aug 12 '10 at 0:20
1  
Works for valid bytes, not just ASCII. –  bstpierre  Aug 12 '10 at 0:30
up vote 9 down vote

you can use the UserString module:

 >>> import UserString
... s = UserString.MutableString('Python')
... print s
Python
>>> s[0] = 'c'
>>> print s
cython
share improve this answer
 
1  
Note that MutableString was deprecated in Python 2.6 and removed in Python 3 - docs.python.org/2/library/…–  msanders  Dec 8 '14 at 15:28
up vote 6 down vote

I'd say the most Pythonic way is to use map():

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

This is the equivalent of writing:

s = "".join(func(c) for c in s)
share improve this answer
 
1  
Minor correction/point: One still needs to re-join the returned list (/iter/map-obj in Py3+). So the above should be:  s = "".join(map(func, s)) –  pythonlarry  Apr 3 '13 at 20:54 
up vote 1 down vote

Strings are iterable and can be walked through like lists. Strings also have a number of basic methods such as .replace() that might be what you're looking for. All string methods return a new string. So instead of modifying the string in place you can simply replace its existing value.

>>> mystring = 'robot drama'
>>> mystring = mystring.replace('r', 'g')
>>> mystring
'gobot dgama'
share improve this answer
 
 
Strings are immutable and cannot be assigned to by member. –  Paul Nathan  Aug 11 '10 at 23:58
 
Correct. All string operations return a copy of the input string. The variable name is NOT immutable, however, so by re-assigning a string operation to the same variable name, you are effectively "mutating" the string. –  jathanism  Aug 12 '10 at 0:00
 
"In the gage case of altegations to a stging, which do not incgease og decgease its length, it would still be useful if one could use the slice notation fog in-place adjustments: myStr[0:3][:] = 'new'".replace("g","r") –  CoDEmanX  Aug 20 '15 at 20:00 
up vote 1 down vote
>>> mystring = "Th1s 1s my str1ng"
>>> mystring.replace("1", "i")
'This is my string'

If you want to store this new string you'll have to mystring = mystring.replace("1", "i"). This is because in Python strings are immutable.

share improve this answer
 
 
1: Don't use "string" as a variable name. 2: That doesn't modify the variable. –  bstpierre  Aug 11 '10 at 23:58
 
That doesn't select by index and modify it. –  Paul Nathan  Aug 12 '10 at 0:00
 
@bstpierre: There you go. :) –  Jungle Hunter  Aug 12 '10 at 0:01 
 
@Paul Nathan: Where was "by index" a requirement? –  S.Lott  Aug 12 '10 at 0:19
up vote 1 down vote

Assigning a particular character to a particular index in a string is not a particularly common operation, so if you find yourself needing to do it, think about whether there may be a better way to accomplish the task. But if you do need to, probably the most standard way would be to convert the string to a list, make your modifications, and then convert it back to a string.

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

EDIT: As posted in bstpierre's answer, bytearray is probably even better for this task than list, as long as you're not working with Unicode strings.

s = 'abcdefgh'
b = bytearray(s)
b[3] = 'r'
s2 = str(b)

你可能感兴趣的:(Python,String)