I think I understand what you're getting at here.
I would probably rebuild the word-so-far on the spot instead of having a persistent string for it, keeping the tested letters separately. When the user tries a new character, make two checks:
See if the guess character has been guessed already: if guess in tried. If so, proceed however you like (penalize or ignore), but don't add the character to the tried-characters list.
If not, see if the character is in the target word: elif guess in word. If not, assess some penalty and add the guess to the tried-characters list.
For any other result: else. Add the guess to the tried-characters list.
To display the user's progress, make a blank string. Go through the target word character-at-a-time: for char in word, like you have been. But instead of trying to modify an extant string, just add the character to the end of the blank string if it's in the tried-characters string, or an underscore if not: show += char if char in tried else "_". Once that for loop is exhausted, display what you've got!
Alternatively, use .join with a slightly different iterator: show = "".join(char if char in tried else '_' for char in word). It'll iterate through word, keeping each letter if it's in your tried-characters string, or substituting an underscore if not, putting whatever is in "" between them (or nothing, if you leave it as ""). It looks like you already know that, though.
At the hazard of completely rewriting your code, this is what it might look like:
## init
word = "mauritius" # the word you're looking for. I chose this one.
tried = str() # initialize a list of tested characters
tryNum = 3 # however many wrong guesses the user gets
...
## in your run loop...
if tryNum: # evaluates 0 as Fasle, if you didn't already know
guess = UserInput() # some means to get the guess from the user; a single-character string.
if guess in tried:
print "Tried that letter already!"
elif guess not in word: # the letter hasn't been tested yet, but isn't in the word, either.
print "Wrong! %d guesses left!" % tryNum
tryNum -= 1
tried += guess
else: # the guess is new (not tried) and it's valid (in the word)
tried += guess
show = str() # this is the string you will display. make a blank one each time.
for char in word:
show += char if char in tried else "_" # if the character has been tried, add it to the output. Otherwise, an underscore.
print show # display the word so far
if show == word:
print "You win!" # Congratulations! You hung a man.
else: # Out of tries; the convict lives another day.
print "Game Over!" # I am not sure how committed to this vocabulary-based execution you really are...
You can swap if tryNum: with while tryNum: and it should work all by itself, after initialization. If you do, there are fun things you can do with continues and breaks, but that goes a bit beyond the scope of your question.
You can swap show = str() and the for char in word: block out with the .join singleton in this next example, too. Change ''.join(..) to ' '.join(..) to add a space between characters/underscores!
This compressed version is probably a bit less Pythonic:
# post-init...
if tryNum:
guess = UserInput()
if guess in tried: pass
elif guess not in word:
print "Wrong! %d guesses left!" % tryNum
tryNum -= 1
tried += guess
else: tried += guess
show = ''.join(char if char in tried else '_' for char in word)
if show == word: print "You win!"
else: print "Game Over!"
This does not answer your first question of "What am I doing wrong?" but I think it might be a better way of going about what you intend? It might be a bit easier to maintain and expand for you, too.
Note: Go ahead and replace UserInput() with something like str(raw_input("Guess a letter!"))[0] if you want to try this thing out on its own.
if letter == guesswhat you need to replace here ?range(x,y)gives all the numbers from x to y-1, so there's no need to subtract 1 again. A simpler way to do this is:wordGuess = '_' * len(word).