HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Changing a character in a string at a specified index position

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
indexcharacterpositionchangingstringspecified

Problem

Could you please tell me what you liked or may have disliked about this code? What can be made better?

```
#!/usr/bin/python3

def change_char_at(ch, s, indx):
"""
Strings in Python are immutable objects. So, it is not possible to change a
certain character in a string in place. For example, an attempt to run the
following code will fail with a TypeError:

s = "spam"
s[1] = "z" # TypeError: 'str' object does not support item assignment

What this function does is it provides you with a nice interface when you
want to change a character in a string at a certain index position. So, use
this function instead of doing everything manually which can sometimes be
tricky. Notice that the character parameter does not necessarily have to be
one character long. It can be an empty string which means that a character
at a certain position will effectively be deleted from the string. If it's
more than one character long, then they all will be inserted into the string
starting at the specified index position.

Parameters:
ch: character to insert
s: string to insert into
indx: index position where to insert the character
"""
# Error handling
if type(ch) is not str:
raise TypeError("first argument must be a string")
if type(s) is not str or not len(s) > 0:
raise TypeError("second argument must be a non-empty string")

length = len(s) - 1
if not(indx >= 0 and indx <= length):
msg = "string index out of range; "
msg += "attempt to access index at {0}; ".format(indx)
msg += "allowable index range 0 to {0}".format(length)
raise IndexError(msg)

# Actual function logic
return s[:indx] + ch + s[indx + 1:]
"""
Another possible implementation:

ls = list(s)
ls[indx] = ch
return ''.join(ls)

This works well too and is equally good, but might be conspired unpythonic
by some compared

Solution

The fact that your function is named change_char_at and the first parameter is named ch both suggest that ch should be a single character. However, the function could easily be abused to splice in any number of characters at that location, including zero. So, you might as well make it obvious and rename the function to string_splice() or something.

I'm not a fan of this function, though. Basically, it's a long-winded way to do s[:indx] + ch + s[indx + 1:] with some validation.

  • if type(ch) is not str seems pointless. If ch is not a string, it would naturally fail with a TypeError anyway during concatenation.



  • if type(s) is not str might be useful validation, but it also goes against Python's duck-typing philosophy.



  • if … not len(s) > 0 is an unjustified special case. If you're going to allow splicing in an arbitrary number of characters, then why shouldn't one be allowed to add something to an empty string? As a consequence of this failure case, the caller will also need to put in a special case to work around this restriction.



  • if not(indx >= 0 and indx



In summary, if you want to do
s[:indx] + ch + s[indx + 1:], then it's probably best to just write that. If you want to write this function anyway, I recommend dropping most, if not all, of the validation.

If you want to do a lot of single-character replacements, then you would probably want to convert the string to a
list or bytestring` instead.

Context

StackExchange Code Review Q#120417, answer score: 3

Revisions (0)

No revisions yet.