String confusion


#1
def reverse(text):
    word = ""
    letters = len(text) - 1
    while letters >= 0:
        word = word + text[letters] #What is this text[letters] doing here?? 
        letters -= 1
    return word


print(reverse("Hello World"))

PLEASE HELP I CANT DO THIS, it’s a combination of a string variable with a string variable! I cannot understand this. I know what it does but what??? I don’t understand the process…


#2

I understand it now but I cant delete the thread. I am such a b-baka X(


#3

letters is probably not a great name for a variable referring to a number. One less than a length is a strange value to hold on to, too.

Also, variables don’t have types! Values do!


#4

It’s you again, you’re the man, man. I understood it right after posting but I see I tangled myself up in something that was supposed to make it easier… darn.


#5

Actually. Index of the last value is totally a sensible thing to hold on to now that I actually read the code…


#6
def reverse(text):
    word = ""
    letter_index_position = len(text) - 1
    while letter_index_position >= 0:
        word = word + text[letter_index_position]
        letter_index_position -= 1
    return word

All gucci now.


#7

I’d go with i haha

Also. To make things a bit difficult for you let me point out that each time you do addition there, you copy all of the previous string!

So, for example to reverse 'abcdefghij', ALL of these would get created:

j
ji
jih
jihg
jihgf
jihgfe
jihgfed
jihgfedc
jihgfedcb
jihgfedcba

By the triangle shape of that you can also tell how much work it is (length * length / 2)

It kind of should be a list. Because that allows appending.
And then join afterwards.


#8

I dont think this is right. Since the variable is reused this should not be an issue right ?

Also addition is not something you should worry about in loops i think.
After some testing i even want to say @kekpop his result is better.

Check for yourself:

import time

def reverse(text):
    word = ""
    letter_index_position = len(text) - 1
    while letter_index_position >= 0:
        word = word + text[letter_index_position]
        letter_index_position -= 1
    return word
	
	
	
def reverseTwo(text):
	result = []
	for i in range(len(text)-1, -1, -1):
		result.append(text[i])
	return "".join(str(x) for x in result)
	
def getRandomString(length):
	result = ''
	for i in range(length):
		result = result + 'a'
	return result

print(reverse("HELLO WORLD !!"))

print(reverseTwo("HELLO WORLD !!"))


# checking efficiency on redicualous large strings.
input = getRandomString(100000) # string with a bunch of 'a' characters

t0 = time.time()
reverse(input) # not printing result its just 'a's anyway
t1 = time.time()
print(t1-t0)  	# output --> 0.17 ish

t0 = time.time()
reverseTwo(input) # not printing result its just 'a's anyway
t1 = time.time()
print(t1-t0)	# output --> 0.28 ish

#9

variables aren’t memory


#10

I dont understand what you mean. If you overide your variable the value in the memory, if not used on some other place, will be overwritten.

in this thread i made an example for it that shows how it is overwritten.


#11

The testing goes that way because CPython does something here that isn’t part of the language itself. It is able to tell that NOBODY else knows about that value, and it can therefore modify it in-place.

If you run the same code in Jython and maybe pypy, you would see a very large difference


#12

What you show in that thread is that the id number is re-used. Not memory.
Id is guaranteed to be unique between currently existing objects. What happens there is that one of them goes out of existence, and a completely new value gets the same id.


#13

so only the last line would keep excisting right ? Isnt the rest just garbage collection ?
How would you test if the memory is still being used ? and how would you know what the values are for this memorie usage ?


#14

Yes the rest gets garbage collected. The problem is the work to create them.
If the string is 1 million characters long, then instead of 1 million amount of work, it’s 1 million * 1 million / 2 – this will be really really slow.

HOWEVER, yes, CPython will do this “right”
The problem is that 1) the code says to do the wrong thing 2) the wrong thing is what will happen in other python implementations

If only targetting CPython then yeah it’s a somewhat reasonable thing to do intentionally. I don’t know whether CPython promises to keep doing it in all their versions though. They might feel that they have to if there’s a lot of code relying on it.


#15
$ python biirrabench.py
!! DLROW OLLEH
!! DLROW OLLEH
0.019551515579223633
0.026768922805786133
$ pypy3 biirrabench.py
!! DLROW OLLEH
!! DLROW OLLEH
4.598165988922119
0.024868488311767578
$ jython biirrabench.py
!! DLROW OLLEH
!! DLROW OLLEH
2.59999990463
0.161999940872

#16

Oh and let me rewrite the code for the second version:

def reverseTwo(text):
	return "".join([text[i] for i in range(len(text)-1, -1, -1)])
$ python biirrabench.py 
!! DLROW OLLEH
!! DLROW OLLEH
0.021166086196899414
0.007839679718017578

#17

I wouldn’t write that either though.
I’d write: (well, without the function, redundant)

def reverseTwo(text):
	return text[::-1]
$ python biirrabench.py 
!! DLROW OLLEH
!! DLROW OLLEH
0.01616048812866211
0.0001289844512939453   <-- that's actually obscene, I wonder if python simply decides to not do it until later

#18

ah i guess your right. i haven’t made the string long enough to see correct results.

I’m not sure why you keep referring to CPython btw. all this code is normal python right ?

also could you explain how you get this sum out of the code ?


#19

I used your length! 100k is fine. Because 100k*100k is a lot, it definitely shows up in a measurement.

That’s the area of a triangle. (print out all the strings, get area, see my third post)
It’s also the number of characters that will be created in total.

The average length will be len/2, and it happens len times -> len * len / 2


#20

Look at my post where I ran different python implementations (cpython, pypy, jython)
cpython is the one from python.org, named so for being written in C