Local variable 'first' referenced before assignment [duplicate] - python

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 7 years ago.
I get a Local variable 'first' referenced before assignment error when I run my code.
def start():
global a
a = [" "," "," "," "," "," "," "," "," "]
global first
first = randrange(2)
def reverse():
if first == 1:
first = 0
else:
first = 1
if first == 1:
turn = "X"
else:
turn = "O"
That is just a part of my code where the error occurs. However when I paste the code into IDLE it works no problem so I don't know why this is happening.
Anyways, my full code (unfinished Tic Tac Toe):
from os import name
from os import system
from random import randrange
from time import sleep
def cls():
system(['clear','cls'][name == 'nt'])
def start():
global a
a = [" "," "," "," "," "," "," "," "," "]
global first
first = randrange(2)
def reverse():
if first == 1:
first = 0
else:
first = 1
if first == 1:
turn = "X"
else:
turn = "O"
while True:
reverse()
cls()
printBoard()
print ""
print "Its %s's turn." % (turn)
print ""
move = raw_input("Enter your move (1-9): ")
if move.isdigit() == True:
move = int(move)
if move in range(9):
move = move - 1
if a[move] == " ":
a[move] = turn
else:
print "Incorrect move: Place taken"
reverse()
sleep(2)
else:
print "Incorrect move: Number out of range"
sleep(2)
else:
print "Incorrect move: Move not a number"
sleep(2)
def printBoard():
cls()
print a[0],"|",a[1],"|",a[2]
print "---------"
print a[3],"|",a[4],"|",a[5]
print "---------"
print a[6],"|",a[7],"|",a[8]
start()

Python scans a function body for any assignments, and if they aren't explicitly declared global, then it creates a local scope variable for that name. Because you assign to first in your reverse() function, and you haven't explicitly declared first to be global within that function's scope, python creates a local variable named first that hides the global one.
It doesn't matter that the assignment comes after the comparison; python implicitly declares all local variables at the beginning of the function.
To fix this you can declare first to be global within the reverse() function, but as others have said, globals should be avoided when possible.

Related

Input function is adding None

I'm trying to use the input function but every time, without fail, the word "None" appears at the end of my question/string (well running), it's capitalized just like that but has no overall effect on the code, it just ruins the project I'm working on.
Here's my code:
import time
import sys
def dp(s):
for c in s:
if c != " ":
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.22)
elif c == " ":
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0)
name = input(dp("Hello, whats your name? "))
Every function in python will return something, and if that something isn't defined it will be None (you can also explicitly return None in a function). So, your dp() function returns None, and so you are effectively calling input(None), which gives the same prompt of None.
Instead, try putting in input() call within the function itself.
def dp(s):
for c in s:
if c != " ":
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.22)
elif c == " ":
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0)
return input()
name = dp("Hello, whats your name? ")

Using console to choose and change a global variable in Python [duplicate]

This question already has answers here:
Cannot change global variables in a function through an exec() statement?
(3 answers)
Closed 2 years ago.
I'm learning python and trying to use a function to choose and change a global variable.
I want to use the console to choose which variable to change and then choose the new value.
I'm using global inside the function to access the variables and I'm using exec() to proceed with the desired modification captured through input(). But something is not working.
Can someone please figure out what is wrong here?
name = "John"
age = 45
gender = "male"
def identify_yourself():
print("My name is " + name + ".")
print("I'm " + str(age) + " years old.")
print("I'm " + gender + ".")
def change_something():
global name, age, gender
something = input("Which variable do you want to change?\n> ")
# I then input "name"
new_value = input("Change to what?\n> ")
# I Then input "Paul"
exec(something + " = '" + new_value + "'")
identify_yourself()
identify_yourself()
# This first prints...
#
# My name is John.
# I'm 45 years old.
# I'm male.
change_something()
# On the second time this SHOULD print...
#
# My name is Paul.
# I'm 45 years old.
# I'm male.
#
# ... but it's not working.
# It keeps printing "My name is John" even after I run the change_something() function
The exec() uses globals() and locals() as defaults for their global and local variables. It defaults to changes in the locals(), not the globals. You therefore have to explicitly tell it to overwrite globals. You can do this the following way:
exec(something + " = '" + new_value + "'", globals())

How do I use user input, obtained through a function, to alter global variables?

I have a global variable that needs to be altered by user input generated by a function.
I'm trying to make a Zork style text game and want the character name, input by the user during a character creation function, to alter a global variable.
I've been able to create a class to store character information and been able to display most of the information in the class on a mock command prompt I have appear when input options are available to the user.
I use a global variable to define the character's name until the character creation stage. I use the 'global' keyword in the creation() function to alter the 'name' variable with user input.
When the prompt is ready to be used it still only displays the name as 00 instead of the input generated during the creation() function
I am exceedingly novice. Any advice, tips or direction would be cherished.
import time
name = "00" ##this is what we want to change
##
def Intro():
print("\n\n\nWelcome to the game.")
time.sleep(1)
print("This is an attempt to make an interactive text based game.")
##
def Creation():
Character_name = input("\nWhat will your Character's name be: ")
time.sleep(1)
print("\nWelcome to the game " + Character_name + " \n" )
time.sleep(1.5)
Character_class = input("In one word, name " + Character_name + "'s profession: ")
t00n = Character_name + " the " + Character_class
global name ##here I am using the global keyword
name = t00n
time.sleep(1)
print("\n" + t00n + "\n")
time.sleep(2)
next_func = input("When ready type 'next' to begin.\n>>>:")
if next_func == "next":
segway()
else:
Jump()
##
def Jump():
Jump_Prompt = input("Just 'Jump' on in\n>>>: ")
if Jump_Prompt == "Jump":
segway1()
else:
Jump()
##
def segway():
print("A room with options to choose from")
prompt()
class Character:
def __init__(self, name, HP, full_HP, AtS, AR):
self.name = name ##should = t00n now?
self.hp = HP
self.full_HP = full_HP
self.AtS = AtS
self.AR = AR
def stat_bar(self):
return '{} {} {} {} {} {}'.format("[Name:]", self.name, "[HP:]", self.hp, "[Max HP:]", self.full_HP)
Player1 = Character(name, 100, 100, 1, 0)
##
def prompt():
_pr = input("<<< " + Character.stat_bar(Player1) + " >>> \n")
return _pr
#Begin
Intro()
Creation()
segway()
##The prompt() function still displays the name as 00 even tho the creation() function is using the 'global' keyword to change the 'name' variable to the user input.
You need to use the global keyword in your prompt, and update Player1.name with that global name
def prompt():
#Take name from global scope
global name
#Assign it to Player1 name
Player1.name = name
_pr = input("<<< " + Character.stat_bar(Player1) + " >>> \n")
return _pr
Then your prompt will work as intended, for example
Welcome to the game.
This is an attempt to make an interactive text based game.
What will your Character's name be: Joe
Welcome to the game Joe
In one word, name Joe's profession: Don
Joe the Don
When ready type 'next' to begin.
>>>:next
A room with options to choose from
<<< [Name:] Joe the Don [HP:] 100 [Max HP:] 100 >>>
Ahhh, took a little bit, but I think I found the problem.
You initialize Player 1 using the name variable before calling Creation(), where you change the global name variable, so Player1 is created with the original name “00.”
Move the line:
Player1 = Character(name, 100, 100, 1, 0)
Put it after Creation() at the bottom but before segway()
Python more or less executes any unindented code (code that isn’t in a function, class, etc.) from top to bottom.
So, moving from top to bottom in your program, it sets name to “00”, then creates Player1 with the original name, then calls Intro(), Creation() (which changes the name to t00n), and finally segway().

I cannot find the error in my Python Code [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Closed 6 years ago.
I am (attempting) to make a hacking game like Hack Run or Hacknet. But only the terminal. I get this error when I try to print the variable 'currentip' at line 86 ("print("You are currently at " + currentip + ".")"):
UnboundLocalError: local variable 'currentip' referenced before assignment
This looks like a simple error but I cannot figure it out. I have assigned it. Multiple times. Maybe I am reading the order execution wrong but I can't find any info that says I am doing it wrong...
Any ideas for cleaning up and making it neater/better is also very much appreciated.
import os
import random
from time import sleep
os.system("cls")
save = {}
ips = {"1337.1337.1337.1337": "Cheater's Stash"}
shells = []
storyips = ["Bitwise Test PC"]
currentip = "1.1.1.1"
homeip = "1.1.1.1"
def resetip():
ip1 = random.randint(1, 999)
ip2 = random.randint(1, 999)
ip3 = random.randint(1, 999)
ip4 = random.randint(1, 999)
homeip = str(ip1) + "." + str(ip2) + "." + str(ip3) + "." + str(ip4)
if homeip in ips:
resetip()
else:
ips[homeip] = "Your Computer"
currentip = homeip
def storyreset():
for x in storyips:
ip = (0, 0, 0, 0)
ip1 = random.randint(1, 999)
ip2 = random.randint(1, 999)
ip3 = random.randint(1, 999)
ip4 = random.randint(1, 999)
ip = str(ip1) + "." + str(ip2) + "." + str(ip3) + "." + str(ip4)
if ip in ips:
storyreset()
else:
ips[ip] = x
def start():
os.system("cls")
print("Python 3.5, HackSim 1.1")
print("")
print("Loading modules...")
print("")
sleep(1)
print("OS Loaded.")
sleep(0.5)
print("HELP Loaded.")
sleep(0.5)
print("FILE USE Loaded.")
sleep(1)
print("CONNECTIONS Loaded.")
sleep(0.5)
print("UTILS Loaded.")
sleep(0.5)
print("HACKS Loaded.")
print("")
sleep(1)
print("Initiating command line...")
sleep(1)
commandline()
def usecommand(c):
if c == "reboot":
print("Rebooting...")
sleep(3)
start()
elif c == "clear":
os.system("cls")
elif c == "quit":
quit()
elif c == "forkbomb":
del ips[currentip]
if homeip in ips:
currentip = "Your Computer"
else:
resetip()
currentip = "Your Computer"
elif "connect " in c:
if c[8:] in ips:
connectip = ips[c[8:]]
print("Connecting to ", connectip, " ", c[8:], "...")
currentip = connectip
else:
print("This ip does not exist.")
elif c == "connect":
print("You are currently at " + currentip + ".")
print("The syntax of this command is: connect <ip>.")
else:
print("Invalid command. Either the command does not exist or check the required syntax.")
def commandline():
while True:
command = input("> ")
usecommand(command)
storyreset()
resetip()
start()
Thanks!
The problem is that you have global variables in your code and you are trying to access them from inside the function without first declaring them global. You need to put a line global currentip at the beginning of your usecommand function.
Also note that if you only used the variable currentip in your function it would work, but if you are both using it and assigning it within the same function the interpreter assumes it is a local variable you are using. Take a look at this:
x = 10
def f():
print x
def f2(arg):
if arg:
x = 20
else:
print x
Running function f() will print 10, but running function f2(0) will produce an error because the interpreter is once again unsure of whether the variable you are using is local or global and assumes it is a local one.
HTH.

variable type change from global variable to method variable why?

I initate a variable globally then when I go to change the variable it's type goes from dictionary (good) to string ( bad) and I am kinda sure why but not really. I am not 100% on python scoping.
The code in full is below please notice I have alot of print statements which I was using as testing. I am including all the code to the point of the issue to give you all a full grasp of what I am trying to do.
totalEntries = 0
print 'this is first ' + str((type(totalEntries))) #prints type int (good)
perPage = 0
currentPage = 1
Pcity = ''
api_data = ''
is_last_page = False
apiCallNum = 1
tableDefined = False
def getApiData(city):
global Pcity
global apiCallNum
global apiEndpoint
Pcity = city
apiEndpoint = #just a link ignore this
api_data = requests.get(apiEndpoint).json()
print(api_data)
print('your testing this' + str(type(api_data))) #prints dict (good)
print ("Current API Call " + str(apiCallNum))
apiCallNum += 1
print('your testing this' + str(type(api_data))) #prints dict (good)
def populateVars():
global totalEntries
print "this is second " + str(type(totalEntries)) #prints int (good)
print('your testing this' + str(type(api_data))) #prints string (bad)
totalEntries = api_data['total_entries']
thank you all
Assignments made to api_data inside getApiData won't be visible anywhere else because you didn't mark it as global.
Add global api_data to the beginning of getApiData.
Incidentally, you only need the global statement if you want to assign to a global variable - you can access their values just fine without the statement. So strictly speaking you don't need global apiEndpoint.

Categories