TypeError : string indices must be integers

Tags: python
By : Simon
Source: Stackoverflow.com
Question!

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.

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 :

def toLower(pStr):

i = 0

for i in pStr:
    if ord(pStr[i]) >= 65 and ord(pStr[i]) <= 90:
        pStr[i] = chr(ord(pStr[i])+28)

return pStr

testStr = "TEST STRING"

print(toLower(testStr))

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

By : Simon


Answers

You are iterating over the string, so each i is bound to a single character, not an integer. That's because Python for loops are Foreach constructs, unlike C.

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

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

If you must generate an index for something, you'd generally use either the range() type to produce those for you, or use enumerate() to produce both an index and the value itself in a loop.

Also, note you don't need to set the for 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 i = 0 is entirely redundant.



You can check for yourself:

Measure-Command {
    1..100000 | ForEach-Object $_
}

1.17s

Measure-Command {
    foreach ($i in (1..100000))
    {
    $i
    }
}

0.15s
By : Avshalom


Yes, there is a performance difference. foreach is faster than ForEach-Object, but requires more memory, because all items ($folders) must be in memory. ForEach-Object processes one item at a time as they're passed through the pipeline, so it has a smaller memory footprint, but isn't as fast as foreach.

See also.



This video can help you solving your question :)
By: admin