This question already has answers here:
Using global variables in a function
(25 answers)
Closed 7 months ago.
I am trying to figure out why I get an UnboundLocalError in my pygame application, Table Wars. Here is a summary of what happens:
The variables, REDGOLD, REDCOMMAND, BLUEGOLD and BLUECOMMAND, are initialised as global variables:
#Red Stat Section
REDGOLD = 50
REDCOMMAND = 100
#Blue Stat Section
BLUEGOLD = 50
BLUECOMMAND = 100
def main():
[...]
global REDGOLD
global REDCOMMAND
global BLUEGOLD
global BLUECOMMAND
This works when spawning units within the main loop, subtracting funds to spawn units.
Right now, I am trying to set up a system so that when a unit dies, the killer refunds the victim's COMMAND and earns GOLD based on what he killed:
class Red_Infantry(pygame.sprite.Sprite):
def __init__(self, screen):
[...]
self.reward = 15
self.cmdback = 5
[...]
def attack(self):
if self.target is None: return
if self.target.health <= 0:
REDGOLD += self.target.reward #These are the problem lines
BLUECOMMAND += self.target.cmdback #They will cause the UnboundLocalError
#when performed
self.target = None
if not self.cooldown_ready(): return
self.target.health -= self.attack_damage
print "Target's health: %d" % self.target.health
This works right up until the unit dies. Then this happens:
Traceback (most recent call last):
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 606, in <module>
main()
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 123, in main
RedTeam.update()
File "C:\Python27\lib\site-packages\pygame\sprite.py", line 399, in update
for s in self.sprites(): s.update(*args)
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 304, in update
self.attack()
File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 320, in attack
REDGOLD += self.target.reward
UnboundLocalError: local variable 'REDGOLD' referenced before assignment
How do I get the global variables mentioned above to change with the attack block? If it helps, I am using Pygame 2.7.x, so nonlocal won't work :/
global make the global variable visible in the current code block. You only put the global statement in main, not in attack.
ADDENDUM
Here is an illustration of the need to use global more than once. Try this:
RED=1
def main():
global RED
RED += 1
print RED
f()
def f():
#global RED
RED += 1
print RED
main()
You will get the error UnboundLocalError: local variable 'RED' referenced before assignment.
Now uncomment the global statement in f and it will work.
The global declaration is active in a LEXICAL, not a DYNAMIC scope.
You need to declare the variable as global in each scope where they are being modified
Better yet find a way to not use globals. Does it make sense for those to be class attributes for example?
Found that variables in main act like global "read only" variables in function. If we try to reassign the value, it will generate error.
Try:
#!/usr/bin/env python
RED=1
A=[1,2,3,4,5,6]
def f():
print A[RED]
f()
It's ok.
But:
#!/usr/bin/env python
RED=1
A=[1,2,3,4,5,6]
def f():
print A[RED]
A = [1,1,1,1,1]
f()
Generate
File "./test.py", line 6, in f
print A[RED]
UnboundLocalError: local variable **'A'** referenced before assignment
and:
#!/usr/bin/env python
RED=1
A=[1,2,3,4,5,6]
def f():
print A[RED]
RED = 2
f()
Generate
File "./test.py", line 6, in f
print A[RED]
UnboundLocalError: local variable **'RED'** referenced before assignment
Related
I'm writing a program in selenium python. I pasted here part of the code from my program (I did not paste all the code because it has 800 lines) with the UnboundLocalError error: local variable 'i' referenced before assignment, the error occurs exactly at i += 1.
global i
i = 0
odpowiadanieobserwowaniestronfb0()
def odpowiadanieobserwowaniestronfb0():
if i > ileraz:
driver.quit
skonczono()
'''
try:
testt = driver.find_element_by_xpath('')
except Exception:
odpowiadanieobserwowaniestronfb1()
zleskonczono1()
'''
def odpowiadanieobserwowaniestronfb1():
i += 1
global keyword tells the function, not the whole module / file, what variables should be considered declared outside the scope of the said function. Try this:
def odpowiadanieobserwowaniestronfb1():
global i
i += 1
There are two options:
You can use your global variable:
def odpowiadanieobserwowaniestronfb1():
global i
i += 1
or you pass the i to the function:
def odpowiadanieobserwowaniestronfb1( i ):
return i += 1
I'm confused. What is different about player1_head compared to the other variables I am printing in the code below? As far as I can tell it should behave the same as the others - it's declared in the global scope, no? I don't think it's a typo.
UnboundLocalError: local variable 'player1_head' referenced before assignment
from turtle import *
from random import randint
from utils import square, vector
player1_xy = vector(-100, 0)
player1_aim = vector(4, 0)
player1_body = []
player1_head = "It looks like I'm assigning here."
def draw():
"Advance player and draw game."
print("xy: ", player1_xy)
print("head: ", player1_head)
print("body: ", player1_body)
player1_xy.move(player1_aim)
player1_head = player1_xy.copy()
player1_body.append(player1_head)
square(player1_xy.x, player1_xy.y, 3, 'red')
update()
ontimer(draw, 200)
setup(420, 420, 370, 0)
hideturtle()
tracer(False)
draw()
done()
Because you failed to declare player1_head as a global, in the draw() function it appears to that function that you're printing out local variable player1_head before it has a value:
print("head: ", player1_head)
# ...
player1_head = player1_xy.copy()
Instead do:
def draw():
""" Advance player and draw game. """
global player1_head
print("xy: ", player1_xy)
print("head: ", player1_head)
print("body: ", player1_body)
player1_xy.move(player1_aim)
player1_head = player1_xy.copy()
player1_body.append(player1_head)
square(player1_xy.x, player1_xy.y, 3, 'red')
update()
ontimer(draw, 200)
The assignment player1_head = player1_xy.copy() in the draw() function is saying to Python that the variable player1_head is a local variable to the function draw(), and since print("head: ", player1_head) is referencing a local variable before its assignment, the error is shown. You can fix this by using player1_head as a global variable (since you're modifying it, same goes for the variable player1_body, since you're doing player1_body.append(player1_head)), like so:
def draw():
"Advance player and draw game."
global player1_head
#...rest of the code
Note however that you should avoid using global variables when possible, this is one the problems that arises from using them (they can be modified by any function, which can sometimes lead to errors and confusions).
Below is my code
global PostgresDatabaseNameSchema
global RedShiftSchemaName
PostgresDatabaseNameSchema = None
RedShiftSchemaName = None
def check_assign_global_values():
if not PostgresDatabaseNameSchema:
PostgresDatabaseNameSchema = "Superman"
if not RedShiftSchemaName:
RedShiftSchemaName = "Ironman"
check_assign_global_values()
But i am getting an error saying
Traceback (most recent call last):
File "example.py", line 13, in <module>
check_assign_global_values()
File "example.py", line 8, in check_assign_global_values
if not PostgresDatabaseNameSchema:
UnboundLocalError: local variable 'PostgresDatabaseNameSchema' referenced before assignment
So can't we access or set the global variables from inside a function ?
global should always be defined inside a function, the reason for this is because it's telling the function that you wanted to use the global variable instead of local ones. You can do so like this:
PostgresDatabaseNameSchema = None
RedShiftSchemaName = None
def check_assign_global_values():
global PostgresDatabaseNameSchema, RedShiftSchemaName
if not PostgresDatabaseNameSchema:
PostgresDatabaseNameSchema = "Superman"
if not RedShiftSchemaName:
RedShiftSchemaName = "Ironman"
check_assign_global_values()
You should have some basic understanding of how to use global. There is many other SO questions out there you can search. Such as this question Using global variables in a function other than the one that created them.
I'm invoking one function using a button click. But it is giving me error: NameError: global name 'new' is not defined ,even though I have defined new as a new window.
My code for a new window:
def result():
root.withdraw()
new = Toplevel()
new.geometry("1105x605+300+300")
button3 = Button(new, text='Select a Query Image',command = matching_image)
button3.pack(padx = 1, pady = 1,anchor='ne')
button3.place( x = 570, y = 60)
The button will invoke matching_image function, and the code will be:
def matching_image():
path1 = tkFileDialog.askopenfilename(filetypes=[("Image File",'.jpg')])
im = Image.open(path1)
resized = im.resize((200, 200),Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(resized)
myvar1 = Label(new,image = tkimage)
myvar1.image = tkimage
myvar1.pack()
myvar1.place(x = 30, y = 100)
And this is giving the error. The error message is as follows:
%run "D:/6th sem/Major project/Code/frame.py"
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\HP\AppData\Local\Enthought\Canopy32\App\appdata\canopy-1.0.3.1262.win-x86\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "D:\6th sem\Major project\Code\frame.py", line 194, in matching_image
myvar1 = Label(new,image = tkimage)
NameError: global name 'new' is not defined
Any suggestions! So that I can solve this error.
Thanks in advance :)
You defined new in a function, so that variable only exists in that function's scope. Therefore, when you try to access it in another scope (here it is the global scope) you will get a NameError as it is not available at that level.
You can fix this by doing global new at the start of the function in which you define it.
This statement puts it in the global scope, meaning that it is defined at the module level. Therefore, you can access it anywhere in the program and you will not get that error.
Like this:
def result():
global new
new = Toplevel()
# Other stuff.
Though note that doing global declarations is considered bad practice. Much better to put your code in class form and assign applicable variables to self.
Your problem is condensed down to this:
def foo():
var = 1
def bar():
print var
foo()
bar()
The principle problem you have is that 'var' is a local, not a global.
This code example works:
def foo():
global var
var = 1
def bar():
print var
foo()
bar()
Because var is declared to be global instead.
I get error UnboundLocal: Local variable T referenced before assignment, however it's not like that:
import ...
T = 0
def do_something():
do_something_else(T) # err at this line
T += 1
def do_something_else(t):
print t
do_something()
That is how my code looks, so it is not reference before assignment. (correct me if I am wrong) What's wrong?
Declare T as global variable:
def do_something():
global T # <--------------
do_something_else(T) # err at this line
T += 1