1

So given this function as an example.

def spaced_word(s):
    i= 0
    t = s[i] + ' '

    while i < len(s) - 2:
        t = t + s[i + 1] + ' '
        i = i + 1
    t= t + s[len(s) - 1]
    return t

This function gives back the string inputted with a space between each character. (e.g. spaced_word('hello') --> 'h e l l o')

However, why is it necessary to use t = t + ... as a statement?

For example, why can't I just use:

s[i] + ' '
i = i + 1

Also, why doesn't the same result appear if I replace the line

t = t + s[i + 1] + ' '

with

s[i] + ' ' + s[i + 1] + ' '

since t = s[i] + ' '?

Resolved. Thank you to all that helped!

3 Answers 3

2

Your question seems to be about why you need to maintain a separate t variable to hold the string as you build it up in your loop, rather than directly changing its values.

The reason is that Python's strings are immutable. You can't insert a space in between two letters of an existing string, because you can't modify that string's contents. Any modifications you want to make will have to be done by creating new strings containing copies of the original string's characters.

The line of code you were asking about, t = t + " " + s[i+1] does the following:

  1. First, it makes a new string, containing a copy of the previous value of t, with a space concatenated to the end. This is a temporary value, not bound to any variable name.
  2. Then a second new string is created, copying the string from step 1 and concatenating a character from s onto the end. Python might be clever enough to reuse the temporary string from step one, rather than copying it, but this is generally not something you can rely on.
  3. Finally, the string created by step 2 above gets bound to the variable t, replacing the old string that had been there (which will be garbage collected, since there's no other references to it).

Your proposed alternative code, s[i + 1] + " " creates a new string, but it doesn't do anything with it. It is not assigned to anything, and so it will be garbage collected immediately. It's important to understand that s[i+1] + " " does not change the string s. Even if tried using different syntax, like s[i+1] += " " it wouldn't work, though in this case you'd get an exception.

Here's a slightly more Pythonic version of your code, which might make its function more clear:

def spaced_words(s):
    result = s[0]           # start with the first letter of the string
    for c in s[1:]:         # iterate over the rest of the string
        result += " " + c   # add a space and the next character to the result
    return result           # when the loop is done, return the result string

The for loop replaces the while loop and explicit indexing from your code. This is much easier to follow. I'm also using the += operator, rather than result = result + otherstuff, but this is in fact not a major difference. Since the result string is immutable, it will generally need to be copied every time a new value is concatenated onto the end. However, CPython (the regular interpreter you get from python.org) has some special logic for appending to strings in this way, and will in fact avoid copying the string most of the time. That's an implementation detail though, and not something you should rely on.

Finally, I want to suggest using the built-in str.join method to do what your current function does more easily and more efficiently. It accepts any iterable object as its argument, and conveniently, a string is an iterable over its characters:

def spaced_word(s):
    return " ".join(s)

I realize though that that's not really your question, but it's good to learn about the built-in features of Python, which almost always do what you need better than code you can write yourself.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome. Your explanation really helped me understand. Thank you :)
1

I didn't look at your code in detail, but there is a much easier way to write the function you're talking about:

def spaced_word( s ):
    return ' '.join( s )

print spaced_word( 'abcde' )

prints:

a b c d e

Edit: OK, now I looked at your code to see if I can answer your immediate question, and the answer is no, I can't. That code is just much too complicated. (Sorry!) It's the kind of code where the complexity should make you take a step back and ask, "Isn't there some easier way to do this?"

Am I unkind by saying this? If so, I sincerely apologize. But sometimes you just need to toss out your code and start over with a simpler approach. Yes, I know this from humbling personal experience, having thrown out a lot of my own code!

Some red flags:

  • There are two different places where a space is appended to the output string

  • There are three different places where a character gets appended to the output. The first character of the string gets special treatment, and so does the last.

  • A loop that runs to the string length minus two.

In Python, as in Ruby and JavaScript and probably quite a few other languages, when you need to insert something in between some other items, without an extra "something" at the end, the first place to look is the join() function or method. In each of those languages, that takes an array and inserts a string between each of the array elements. It's a great way to do this kind of operation.

Given that, then the only thing remaining is to turn the original string into an array (a list in Python). The way you do that varies. In Python, you could use list(string) - although you don't even need to do that, because Python strings are iterable and you can do a join on them directly just as you could do with a Python list. (Thanks to @Blckknght for pointing that out.) In Ruby or JavaScript, it's string.split('') - interestingly enough, the syntax is identical in those two languages.

Then you just take the result and do a join(' ') on it in the appropriate syntax for that language. The code is remarkably similar in all three languages.

Ruby:

def spaced_word( s )
    s.split('').join(' ')
end

JavaScript:

function spacedWord( s ) {
    return s.split('').join(' ');
}

Python:

def spaced_word( s ):
    return ' '.join( s )

Or to make it a bit more similar to the other two languages:

def spaced_word( s ):
    return ' '.join( list(s) )

This raises a (hopefully) interesting point. My first approach to the Python code was the second version with the explicit list(s). I've been coding in JavaScript, Python, and Ruby lately, but mostly the last week or so has been JavaScript. So when I wrote a bit of Python code, I naturally fell into a more JavaScript-style approach: first convert the string to an array (list) and then call join on it. In JavaScript, you can't call join directly on a string. But in Python you can!

Perhaps something similar happened in your code? The way you wrote it with a careful character-by-character loop is how you would do it in in C and some other languages. It's a natural tendency to carry over coding patterns from one language to another, just as I wrote my Python code from a JavaScript mindset.

For myself, I know I have to constantly fight that and think in terms of the language I'm currently coding in and what features it offers. Python, along with Ruby and JavaScript and other similar languages, offer a wealth of string and array/list manipulation functions, so that's the place to look before writing more detailed code of your own.

2 Comments

There's no need for the list call in your join code. Python's strings are iterable!
@Blckknght - D'oh! Thank you. This is what happens when I switch back and forth among these three languages daily. You can tell I have been doing more JavaScript the last few days, when I took a more JavaScript-ish approach in the Python code. :-)
-1

in memory variable s

there is a value like 'hello' means s='hello'

you are storing in memory variable 't' above value with every letter with space

s[i] + ' ' + s[i + 1] + ' '
s[1] = ' ' + s[1 + 1] + ' '
s[1] = ' ' + h        + ' '
s[1] = ' h '    // here you are getting space before & after  s[1 + 1]

so your result comes like ' h e l l o '

while t = t + s[i + 1] + ' '
gives result 'h e l l o '

1 Comment

I'm not sure that I really understand what you're saying in this answer, but anything that tries to assign to indexes of a string will fail in Python, since strings are immutable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.