7/15 reverse


#1

This is my code:

def reverse(text):
    new = []
    text = list(text)
    count = 0
    while count<len(text):
        new.append(text[-1:])
        del(text[-1:])
        count+=1
    return str(new)

it returns "[['!'], ['n'], ['o'], ['h']]". I want it to return "!nohtyp"

How come it fails to do the last three iterations? (that is: T, Y and P)
How do i get rid of the quotation marks and brackets? Simple .join() or str() doesn't work.


#2

@markrensen

You use join as follows,

a = ['a', 'b', 'c']
print(''.join(a))
# OUTPUT: 'abc'
``` 

You have to tell it how you want to join the list of items, if you put the char 'a' in for example,

```python
'a'.join(a)
# OUTPUT: 'aabac'

Easy enough?


#3

simple way, no need to create a list and work with it

def reverse(text):
reverse=" "
for char in text:
reverse = char+ reverse
return reverse


#4

@microninja60406
Strings are not mutable, you can't "add" to them, only create new ones. A list makes far more sense than repeatedly re-creating the parts that have already been put in place.


#5

so its better to create a list fill a list with characters and create a string then it is to overwrite the same block?


#6

You're not overwriting anything.

1) You'll construct a new string, this will most definitely not be in the same location as the old string because that still exists.
2) The name (variable) is then made to point at the new value instead of the old one.
3) Python will notice that there aren't any references to the old string any more, and can now remove it from memory. This happens automatically and may not happen at once. This is called garbage collection.

If you create a string of length 1 million one character at a time, creating a new string each time, then you will have copied a total of 500000*1000000 characters. (One million strings are created, and on average it will be half a million characters long)

That said, there's a hack in CPython (that's the standard implementation) where it actually changes the string instead of re-creating it, if it sees that the reference count for that string indicates that there are no other references to it so that it won't break anything by changing it anyway, it's just faster. But your code is saying to do it in a very slow way, it's better to write it the way it's supposed to happen. And if you run your code in another Python version, you won't get this hack, which again, you shouldn't rely on even if it was always there.


#7

oh, I see, thanks for taking the time to explain that.


#8

So if we think about how we want this to be done, we would want a block in memory, we even already know how large it needs to be from the length of the original, and we'd add one character at a time. Done. ...We can't do this in Python, we don't have direct memory access, so yeah, a list. There's gonna be overhead. Python modules can be written in C though and there we can do that kind of thing. Reversing can be done with slice notation ([::-1]) and that functionality is mostly or fully in C code.


#9

@markrensen
to get all the letters, perhaps this would be simpler:
for n in range(len(new)):
new.append(x[len(x)-n-1:len(x)-n])
this should create a list of all the letters in a string "x"


#10

I've solved it. It's a bit like you're solution. Range seems to work perfectly for this problem as it allows to iterate backwards.

def reverse(text):
    new = [] 
    for i in range(len(text)-1,-1,-1):
        new.append(text[i])  
    return "".join(new)