Changing a character in a string at a specified index position
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) &gt; 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 &gt;= 0 and indx &lt;= length) is weird because length isn't actually the length of the string; it's one less than that.  It could be more succinctly written as if not 0 &lt;= indx &lt; len(s).  But Python's negative indexing is a feature, not a bug.  Why would you want to defeat the convenience?


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.