0

My question is when we use a variable in a while loop before changing the variable we have it assigned to (i.e on the Right hand side of the equal to) why does this new variable we supposedly assigned the next variables previous value to change?

I realise the phrasing of my question isn't entirely spot on, so in laymans terms, in my program i'm writing a variable called predispto disp before I change the value of displater in the while loop. Here i'm assuming all the code in python runs from top to bottom.

So here's an example of what value predisp holds so if disp = ['_','_']

predisp = ['_','_']

which is fine. But the moment I enter a letter as part of my hangman guess the value of disp becomes ['u','_'] but the problem is predisp also becomes ['u','_'] which is not what I want. I want it to always have the previous value of disp before it undergoes any changes. I'm new to python so I don't really understand how all the variables work, i'm more used to them in C++. Here's the code (it's for a simple hangman game i'm writing).

# Created by Zur-en-Arrh

import random  # Useful to select a topic from the file.


# Functions

def same_letter(user_letter, word_to_guess):
    if user_letter == word_to_guess:
        return True
    else:
        return False

def wrong_guess(prevdisp,currdisp):
    if prevdisp == currdisp:
        return True
    else:
        return False

# Dealing with the file.
filename = input("Which file do you want to play with ")
topics = str(open(filename, 'r').read())
list_of_topics = topics.split()  # This is the list that contains the topics randomly selected from the file.
guess_me = list(list_of_topics[random.randint(0, len(list_of_topics) - 1)]) # This is what the user will need to figure out.

# Printing out the Dashes for the user.
disp = []
for i in range(0, len(guess_me)):
    disp.append("_")

# This is just the declaration of the number of wrong guesses. This'll always be 0 at the start of the game.
wrong_guesses = 0

# While loop for game. Also note in hangman, you're only allowed 5 wrong guesses till the body is complete.
while wrong_guesses < 6:
    print(' '.join(disp))  # Prints the game in an acceptable format to the user.
    predisp = disp
    if disp == guess_me:  # end the game when the user wins.
        break
    user_guess = str(input("Which letter do you think will there be? "))
    for i in range(len(guess_me)):
        if same_letter(user_guess, guess_me[i]):
            disp[i] = user_guess
    print(predisp)
    if wrong_guess(predisp, disp):
        wrong_guesses += 1

    if wrong_guesses == 6:
        print("You got hung! Better luck next time")
        break

if wrong_guesses < 6:
    print("Well Done you won the game!")
Afr0
  • 41
  • 1
  • 10
  • Thanks for the help. Do you have a book where you read python from? I really need to hone my skills. – Afr0 Jul 24 '16 at 07:03
  • You may find this article helpful: [Facts and myths about Python names and values](http://nedbatchelder.com/text/names.html), which was written by SO veteran Ned Batchelder. – PM 2Ring Jul 24 '16 at 07:12
  • Nope, sorry, I learned python through hands-on programming, no books involved. But I learned quite a few things here on SO. Sometimes clicking questions you know you can't answer still pays off! – Aran-Fey Jul 24 '16 at 07:13
  • there's a ton of material on learning python both online and in books. The [Tutorial](https://docs.python.org/2.7/tutorial/) included in the standard documentation is also quite helpful for newcomers. As for pointers on books checkout [this question](http://stackoverflow.com/questions/328577/python-for-c-developers) – miraculixx Jul 24 '16 at 07:49

1 Answers1

2

In Python, variables are references to objects:

disp = []

creates a new list object and makes it accessible by the name disp. What it really does is set disp to point to the newly created list object. The assignment statement

predisp = disp

does the same thing, i.e. it sets predisp to reference the same list object as disp. Thus any change applied to the object that disp points to is also visible in the object that predisp points to - it's the very same object.

One way to avoid this is to create a copy on assignment:

predisp = disp[:]

This can be easily verified by using the id function:

disp = ['_'] * 3
predisp = disp
id(disp), id(predisp)
# same object ids for both variables
=> (4303250784, 4303250784)

predisp = disp[:]
id(disp), id(predisp)
# different object ids
=> (4303250784, 4303043832)
miraculixx
  • 10,034
  • 2
  • 41
  • 60
  • Thanks ! I didn't really know too much on how the pointer automatically updates itself. I have another question though. In c++ a while loop breaks immediately when the condition is violated. In python however, I have to type out a break statement for that very condition. Is there any way around this? – Afr0 Jul 24 '16 at 07:08
  • @Afr0 Loops work the same way in C++ and Python. In both languages the condition is checked at the start of the loop. What makes you think there's a difference? – Aran-Fey Jul 24 '16 at 07:16
  • The pointer does not automatically update itself. In C++ terms a Python variable is a reference to an object, so when you change the object this change will be visible via all variables that are references to this object. – miraculixx Jul 24 '16 at 07:17
  • What I meant by the difference in while loops is like, suppose in c++ You have something like (running = true) while(running) then somewhere in the body, you make running = false. In c++ it just exits the loop, doesn't execute anything under the violation of the while loop condition, In python, it'll execute the rest of the code right until the end of the main body of the loop, so if there's any code underneath the line where you violate the loop condition, it proceeds to finish the rest of the code (unless you break). – Afr0 Jul 24 '16 at 07:20
  • I'm not sure how you reach this conclusion, in C++ like in Python, the [while condition](http://en.cppreference.com/w/cpp/language/while) is checked at the [beginning of the loop](http://cpp.sh/6vsnn), not in between. In both languages you are free to explictely `break` out of it if you don't want any further statements to be executed, or `continue` on the next round. – miraculixx Jul 24 '16 at 07:37
  • I sincerely apologise. In my earlier time on c++ I never added code ahead of me violating the loop condition, so I never knew about it and just assumed it. Thanks for the clarification though! – Afr0 Jul 24 '16 at 07:57
  • You're welcome. No need to apologise. – miraculixx Jul 24 '16 at 07:58