local variable 'location' referenced before assignment-text adventure - python

I am working on a text adventure as my first python project. I am using a template, (coping code from youtube tutorial). but instead of creating a game loop, I want it to be a function, to be executed when the player types in a command. (that part is working).
Here is the code from the tutorial:
Text_Adventure
bridge = ("Bridge", "You are on the bridge of a spaceship, sitting in the captains chair. ")
readyRoom = ("Ready Room" , "The captains ready room ")
lift = ("Lift" , "A turbolift that takes you throughout the ship. ")
transitions = {
bridge: (readyRoom, lift),
readyRoom: (bridge,),
lift: (bridge,)
}
location = bridge
while True:
print (location[1])
print ("You can go to these places: ")
for (i, t) in enumerate(transitions[location]):
print (i + 1, t[0])
choice = int(input('Choose one: '))
location = transitions[location][choice - 1]
That part works okay, but when I try to turn it into a function:
Text_Adventure
bridge = ("Bridge", "You are on the bridge of a spaceship, sitting in the captains chair. ")
readyRoom = ("Ready Room" , "The captains ready room ")
lift = ("Lift" , "A turbolift that takes you throughout the ship. ")
transitions = {
bridge: (readyRoom, lift),
readyRoom: (bridge,),
lift: (bridge,)
}
location = bridge
def travel():
print (location[1])
print ("You can go to these places: ")
for (i, t) in enumerate(transitions[location]):
print (i + 1, t[0])
choice = int(input('Choose one: '))
location = transitions[location][choice - 1]
travel()
I get the error message:
UnboundLocalError: local variable 'location' referenced before assignment
I know that the best way to learn something is by finding the answer yourself. I have been searching for awhile now and am not getting anywhere, Any help would be greatly appreciated, Thank you.

This can be simplified quite a bit:
>>> a = 1
>>> def foo():
... print a
... a = 3
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'a' referenced before assignment
What's happening
When python sees a the first time in the function, it is a non-local variable (in this case, a global). The second time though, since you're assigning to it, python thinks it is a local variable -- But the name is already taken by a global variable which leads to the error.
There are a few workarounds -- You can declare a as global so that python will know that when you say a = 3, you mean that the global variable a is 3. Personally though, I would advise you beat on the code some more so that you no longer need a global variable. 99 times out of 100, if you're using global, there's probably a better way to refactor the code so you don't need it.

If you write to a global variable you should use global to declare it.
instead this:
def travel():
put this:
def travel():
global location

Thank you for the help, I dont think Ill keep it like this, but it works for now:
#Simplefied version:
a = 1
def foo():
global a
a = 3
print a
def getFoo():
print a
print "foo results: "
foo()
print "getFoo results: "
getFoo()
Prints:
foo results:
3
getFoo results:
3
I was having trouble calling "a" from another function, that's why I displayed the function and the result separately. Its working for now, Thank You

Related

Trying to get my python program to run but I keep getting a variable assignment error. Any ideas as to what I am doing wrong?

def main():
name = ''.join(user_word.lower().split())
name = name.replace('-','') # what?
limit = len(name)
phrase = True
while running:
temp_phrase = phrase.replace(' ', '')
if len(temp_phrase) < limit:
print(f"length of anagram phrase = {len(temp_phrase)}")
find_anagram(name, dict_file)
print("Current anagram phrase =", end = " ")
print(phrase, file=sys.stderr)
choice, name = process_choice(name)
phrase += choice + ' '
elif len(temp_phrase) == limit:
print("\n**FINISHED!!**\n")
print("Anagram of name", end = " ")
print(phrase, file=sys.stderr)
print()
try_again = input("\n\nWant to try again? (Press Enter or else 'n' to quit)\n")
if try_again.lower() == 'n':
running = False
sys.exit()
else:
main()
after running my code I keep getting the error
UnboundLocalError: local variable 'running' referenced before assignment
so I tried making a variable named running in my main function's argument but I got a different error so I just figure I would try to work out this first. Any clue as to how to fix it.
Side note: this problem is from the book impractical python projects (chapter 3 project 5), I copied almost every bit of code so I'm not sure how it isn't working.
The reason you are getting a variable referenced before assignment error is because, as the error describes, you are referencing a variable before assigning any value to it.
The variable running is only referenced inside the while loop, not before. for this to work, you would have to add a line above your while loop assigning a value to running.
Consider this example:
def my_function():
print(my_variable)
my_variable = 'this is a string'
my_function()
In this example, I attempted to print my_variable. However, there was nothing assigned to it before I tried to print it. So the output is the following:
UnboundLocalError: local variable 'my_variable' referenced before assignment
However, if I assign the variable some value before I print it like this, I get the output I am expecting.
def my_function():
my_variable = 'this is a string'
print(my_variable)
my_function()
Output:
this is a string
You may ask why this happens, shouldn't python be able to see that I assigned a value to it and just print that value? The answer to that question is no. To put it simply, Python is executed from top to bottom, so when there is an attempt to print my_variable without assigning anything to it above, the code crashes. Here is some info on how python code works.

local variable 'output_file' referenced before, this code worked a few weeks ago, now it doesnt work how is that possible?

This thing is hard to post code and context inside of.
#This is a menu driven multiplication game. i am attemtping to save the high
#score in a file named multiplication_game.txt...
def single_player():
in_file = open('multiplication_game.txt', 'r')
highest_times_selection = int(in_file.readline())
print('\n____now lets see how u do on the times tables____')
correct = 0
missed = 0
times_selection = int(input(
'\nPlease enter a times time table integer to practice: '))
#This simple generates the multiplation questions and checks for right or
#wrong.
for number in range(0,11):
print(times_selection, 'x' , number, '=')
user_answer=int(input('answer: '))
correct_answer = times_selection * number
if user_answer == correct_answer:
correct+=1
else:
missed+=1
#This is where if its a perfect score and a high times table than the
#previous saved score it should be opened and the new score saved in the
#text document.
if missed == 0 and times_selection > highest_times_selection :
output_file = open('multiplication_game.txt', 'w')
name = input('You have the highest Score!!\n enter your name: ')
output_file.write(str(times_selection)+ '\n')
output_file.write(name + '\n')
else:
print('you missed ', missed, 'and got', correct,'correct\n')
output_file.close()
Try to define output_file = None before any assignment of it.
Tip: before your last if-else condition.
This looks like homework, so I don't want to give you the answer but rather lead you to it.
Take a look at your if/else for your high score table, and walk through your code twice, taking a different branch (different part of the if/else) each time you reach this spot. Write down the variable names on paper as you define them, starting over with a new sheet of paper each time you walk through. If you access a variable, check it off on your list. If you try to access a variable that's not on your list, it's the same as python saying local variable referenced before assignment -- you're trying to access it before you've defined it.
Hope this helps, both in figuring out your problem and learning how to debug in the future.

Python: Using a variable with a value defined in 1 function, being used in another function

def getValidSeason( ):
season = input ( "Enter a season between 1980 and 2016: " )
while season < 1980 or season > 2016:
season = input ( "Enter a season between 1980 and 2016: " )
return season
def getValidDriver( ):
driver = input ( "Enter a driver's name: " )
# This is where the first problem is
# I want to be able to use the value of season from getValidSeason( )
# in the getValidDriver( ) function
while getValidSeason( ) != 1980 and driver != "Steve Park" or driver != "Jamie McMurray"
driver = input ( "Enter a driver's name: " )
return driver
def printResults( ):
# Basically the same as before, I want the value of the driver
# variable defined in the getValidDriver( ) to be used in the print results( ) function
print ( "The driver being selected is",getValidDriver( ) )
def main( ):
# I don't believe my question has anything to do with what you put in the main function , but I might be wrong.
I looked around and could not find help with my problem. I am sorry if there is already a solution out there, but I couldn't find anything. Maybe I was wrong. I'm struggling with programming. I did find a question on this website that was basically the same question but it involved an earlier version of Python, and they were talking about stuff that is no longer used in the current version of Python.
Thanks for the help.
Your code is very close (although I don't understand the condition of the while loop). I cleaned up the formatting such as lowercase R in return and spacing conventions in function calls. I changed the inputs to convert to ints in getValidSeason() since you are trying to get strings. I also added some print lines in the while loop for my own benefit.
Also importantly, you don't need a main here (although it would be ok), but you do need to call your printResults() function to get the code running (the very last line of code). Let me know if you have questions about something I did or didn't explain.
CODE:
def getValidSeason():
season = int(input("Enter a season between 1980 and 2016: "))
while season < 1980 or season > 2016:
season = int(input("Enter a season between 1980 and 2016: "))
return season
def getValidDriver():
driver = input("Enter a driver's name: ")
season = getValidSeason()
# This is where the first problem is
# I want to be able to use the value of season from getValidSeason( )
# in the getValidDriver() function
#EDIT: Not sure what logic you actually want here
while season != 1980 and driver != "Steve Park" or driver != "Jamie McMurray":
print('Last driver selected was: '+str(driver))
print('Last season selected was: '+str(season))
driver = input("Enter a driver's name: ")
season = getValidSeason()
return driver
def printResults():
# Basically the same as before, I want the value of the driver
# variable defined in the getValidDriver() to be used in the print results() function
valid_driver = getValidDriver()
print ("The driver being selected is",valid_driver)
printResults()
EDIT:
#This is Function "func1"
#It takes the variable "name" as its one and only argument
# and it adds '_1' to the end of it before returning name
def func1(name):
print('In func1 you passed in the name: '+name)
print('Adding "_1" to the end of the name')
name = name+'_1'
print('In func1 your new name is: '+name)
print('')
return name
#Just like func1
def func2(name):
print('In func2 you passed in the name: '+name)
print('Adding "_2" to the end of the name')
name = name+'_2'
print('In func2 your new name is: '+name)
print('')
return name
#Function that will ask the user for a name
#Doesn't take any arguments
#Returns the name
def get_name():
name = 'Steve' #<-- just set to always be steve for now (you can replace this w/ an 'input()')
print('Your original name was '+name)
print('')
name_f1 = func1(name) #<-- original name w/ '_1' added to the back
name_f2 = func2(name) #<-- original name w/ '_2' added to the back
name_f1_f2 = func2(name_f1) #<-- orig name w' '_1_2' added to the back
name_f2_f1 = func1(name_f2) #<-- orig name w' '_2_1' added to the back
return name
#Call the get_name function which will then call func1 and func2
get_name()
You probably want to save the functions' return value in a variable in the other function. Here's an example for printResults:
def printResults():
driver = getValidDriver()
# you can now use the 'driver' variable
print("The driver being selected is", driver)
Python Course Shows that you simply need to add the global flag if you want to declare the variable as global inside a function. to further quote Python Course :
"The way Python uses global and local variables is maverick. While in many or most other programming languages variables are treated as global if not otherwise declared, Python deals with variables the other way around. They are local, if not otherwise declared."
I am not sure if this will resolve your issue completely since you are returning the variable back out. Thats simply the first thing I noticed about your code.
"I believe I understood the code you just put up. I'm getting my new keyboard in a couple days so I can't type the code yet, but I think I understand what is going on there. I don't think it answered my question though, unless I am missing something. Let's say in get_name( ) it asks the user to type in a name, and the user types in Tom. The variable that stores this is called name1. Now I want to use the variable name1 in multiple different functions, but I want the value of name1 to automatically be = to the user input defined in get_name( ) without the user having to type it again.
I think I could ask the user the question by using a global variable to ask it, but isn't it proper coding to have it inside a function? Functions are supposed to do 1 thing each and be used to break the program up. Putting the question outside of a function I think you aren't supposed to do. "
I read your comments on the comment section. I posted them above. I think the only thin you can do is call the function or created a global variable.

Can i have multiple global varibles within a python script?

Is it possible to have more than one global variable within a python script?
import os,csv,random
def user():
global Forname
Forname = input('What is your forname? ').capitalize()
while True:
try:
global answerr
answerr = input('Welcome to the phone troubleshooting system '
'\nApple\nSamsung '
'\nOut of the following options enter the name of the device you own ').lower()
except ValueError:
continue
if answerr in ('apple','samsung'):
break
myfile = open(answerr+'_device.csv','r')
answer = input(Forname + ', do you have anymore problems? ').lower()
if 'yes' in answer:
#do whatever
else:
#do whatever
Using the global variable 'answerr' I'd like to open a csv file, and the refer to the user with the forname they input, but I want to use them multiple times through out my code within def functions. I apologise in advance if you do not understand what I'm asking, I'm relatively new to coding given the fact that I'm still a school student.
Of course it's possible. But there is absolutely no reason to use any global variables in this code, let alone multiple.
The point of a function is that it can return a value:
def user():
forename = input('What is your forename? ').capitalize()
return forename
Can I have multiple global variables within a Python script?
Yes and here's how:
When you're assigning any variable at the top-level of a module like: n = "Stackoverflow!" then your variable is global automatically. So let's say we have this modules:
#globals.py
x = 2 + 2
y = 5 + x
both x and y are global variables which means they're accessible to functions, classes and so on. *Just remember any assignment at the top-level of a module is actually global (this is what we call a global scope and it can contain as much variables as your memory allows). This is just like the code you posted. However, what we cannot have is same named variables in any scope:
same = 20
same = "s"
print(same)
will print s, not 20.
Hope you'll find this helpful :-)

Why do I get an UnboundLocalError in my function?

I am newbie, trying to learn python.
According to this article http://www.tutorialspoint.com/python/python_modules.htm, I get an UnboundLocalError in the following code but I don't understand why:
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
# global Money
Money = Money + 1
print Money
AddMoney()
print Money
But the below code works fine
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
# global Money
Money = 1
print Money //2000
AddMoney()
print Money //2000
They explain things in the article, but I'm still not sure that I understand. Why do I get an UnboundLocalError in the first example, but not in the second?
As you've mentioned, the article does explain a little bit, but not very much about why.
When you're programming and you write the name of something, the computer has to know where to go look for that thing. The where is a term known as scope. All variables in Python have a scope. Here are some examples to illustrate:
from __future__ import print_function
value = 'blue'
def fun():
value = 'yellow'
print("Value in function: ", value)
print("Value before: ", value)
fun()
print("Value after: ", value)
# Output:
#
# Value before: blue
# Value in function: yellow
# Value after: blue
In this script you define value to be 'blue'. Then inside the function you set it to 'yellow'. But why does it not stay 'yellow' after the function is called? Scoping.
When you define value = 'yellow' in your function, the name value is bound to 'yellow' only inside the current block (a function, in this case). You'll hear the terms shadow or hiding to explain what's happening here, because that's effectively what's happening. You are hiding the original value with a new value, but once your function ends, so does your new value.
You can see this by using the globals()and locals() builtins
from __future__ import print_function
from pprint import pprint
value = 'blue'
def fun():
print("Globals in function: ")
pprint(globals())
print("Locals in function: ")
pprint(locals())
value = 'yellow'
print("Value in function: ", value)
print("Globals at end of function: ")
pprint(globals())
print("Locals at end of function: ")
pprint(locals())
print("Globals before function: ")
pprint(globals())
print("Locals before function: ")
pprint(locals())
print("Value before: ", value)
fun()
print("Value after: ", value)
print("Globals after function: ")
pprint(globals())
print("Locals after function: ")
pprint(locals())
Now, python has a global keyword that allows you to tell Python that instead of looking inside the local scope, you want to look in the global scope for these variables:
from __future__ import print_function
value = 'blue'
def fun():
global value
value = 'yellow'
print("Value in function: ", value)
print("Value before: ", value)
fun()
print("Value after: ", value)
# Output:
#
# Value before: blue
# Value in function: yellow
# Value after: yellow
In Python, it will try to resolve names first in the local scope, and then in the global scope, which means you can write something like this:
from __future__ import print_function
value = 'blue'
def fun():
print("Value in function: ", value)
print("Value before: ", value)
fun()
print("Value after: ", value)
# Output:
#
# Value before: blue
# Value in function: blue
# Value after: blue
But if that works, then why doesn't your first example, with Money = Money + 1? The answer is simple, though perhaps unexpected:
Because you are trying to redefine Money in your function (the Money = part), it cannot go look for your variable in the global scope, because it doesn't know if you meant to use the global version or the local version, and you get an UnboundLocalError. So you need to tell Python what you mean: Did you want to use the global version, or should you be using something locally?
By declaring global Money, you tell Python explicitly that you want to use the global version. But if you want to use something local then you'll need to use a different name, or define Money before you try to use it as in Money + 1.
AddMoney doesnt know Money variable has been defined before so it crashes with local variable 'Money' referenced before assignment thinking is a local variable which should have been declared inside AddMoney class.
If you uncomment the global Money line inside AddMoney class it will work.
Also the second example is working because in the line Money = 1 you are not using Money variable, you are just asigning a value to Money and overriding the global value
Preface: I'm going with the assumption that the space before Money = 2000 in the second snippet is a mistake, because whitespace is significant in Python, but I don't think it actually makes a change here.
In your first example Money = Money + 1 is trying to read from a variable and then assign a new value to it. Money doesn't exist in the local scope, so it throws an error. The second example is only assigning a value to a variable. AddMoney() creates a local variable called Money and then does nothing with it. The Money from the outer scope is unchanged, as your comments indicate.
The reason is the conflict between globals and local scope variables
(As others have said)
declaring money as global in the function shall do good
Money = 2000
def AddMoney():
global Money
Money = Money + 1
In both functions, you need to delete the hashtag in the line '# global Money' in order for the function to work properly. Hashtags in Python cause the rest of the line to be 'commented', which are lines that will not affect your code and instead act as notes to the developer.
This code will work properly:
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
global Money
Money = Money + 1
print Money
AddMoney()
print Money
In your second piece of code, the function isn't redefining the variable money outside of the function's environment, so while an error is not appearing, you are not accomplishing what you want with the code. Again, deleting the hashtag (uncommenting) will solve your problem. This code will work:
Money = 2000
def AddMoney():
# Uncomment the following line to fix the code:
global Money
Money = 1
print Money //2000
AddMoney()
print Money //2000
Hope this helps!

Categories