TypeError : string indices must be integers
<p>I've returned to Python after a few years doing C code and I'm a little confused while training myself to get my Python coding habits back.</p>

<p>I've tried to run this little, very simple, piece of code but I keep getting a TypeError as described in the title. I've searched a lot but cannot figure out what is the problem with this :</p>

<pre><code>def toLower(pStr):

i = 0

for i in pStr:
    if ord(pStr[i]) &gt;= 65 and ord(pStr[i]) &lt;= 90:
        pStr[i] = chr(ord(pStr[i])+28)

return pStr

testStr = "TEST STRING"

print(toLower(testStr))
</code></pre>

<p>Considering that <code>i</code> is an integer, I don't understand why I get this error. Maybe I think too much like i'm doing C IDK.</p>

<p>You are iterating over the string, so each <code>i</code> is bound to a single character, <strong>not</strong> an integer. That's because Python <code>for</code> loops are <a href="https://en.wikipedia.org/wiki/Foreach_loop" rel="nofollow">Foreach constructs</a>, unlike C.</p>

<p>Just use that character directly, no need to index back into the string. Python strings are also <em>immutable</em>, so you can't replace characters in the string object. Build a new object:</p>

<pre><code>def toLower(pStr):
    output = []
    for char in pStr:
        if ord(char) &gt;= 65 and ord(char) &lt;= 90:
            char = chr(ord(char)+28))
        output.append(char)
    return ''.join(output)
</code></pre>

<p>If you <em>must</em> generate an index for something, you'd generally use either the <a href="https://docs.python.org/3/library/stdtypes.html#ranges" rel="nofollow"><code>range()</code> type</a> to produce those for you, or use <a href="https://docs.python.org/3/library/functions.html#enumerate" rel="nofollow"><code>enumerate()</code></a> to produce both an index <em>and</em> the value itself in a loop.</p>

<p>Also, note you don't need to set the <code>for</code> loop target name to a default before the loop unless you need to handle the case where the loop iterable is empty and you expect to use the target name after the loop. In other words, your <code>i = 0</code> is entirely redundant.</p>

python