Python alter external variable from within function - python

When I run this it works, but it says
"name 'select_place' is assigned to before global declaration"
When I get rid of the second global, no comment appears, but as select_place is no longer global it is not readable (if selected) in my last line of code.
I'm really new to python, ideally I'd like a way of not using the global command but after searching i still can't find anything that helps.
My code:
def attempt(x):
if location =='a':
global select_place
select_place = 0
if location =='b'
global select_place
select_place = 1
place = ([a,b,c,d])
This is the start of some turtle graphics
def Draw_piece_a(Top_right):
goto(place[select_place])

You need to declare the variable first, additionally the function code can be made clearer:
select_place = False
def attempt(x):
global select_place
if location == 'a':
select_place = 0
elif location == 'b':
select_place = 1
Also, there is no return value for attempt(), is this what you want?

Related

Global variable is not defined - Python and PyGame

i try to create a Flappy Bird clone. When i try to define some Global variables visual studio said me that this variables aren't defined in global scope.
Some could help me??
I tried to move the variables in the global scope and it works, but i don't understand why this solution doesn 't work.
This is my code
Thanks in advance
import pygame
import random
pygame.init()
background = pygame.image.load('img/background.png')
base = pygame.image.load('img/base.png')
bird = pygame.image.load('img/bird.png')
gameover = pygame.image.load('img/gameover.png')
pipe_down = pygame.image.load('img/pipe.png')
pipe_up = pygame.transform.flip(pipe_down, False, True)
windowX = 288
winwowY = 512
frame_rate = 50
display_surface = pygame.display.set_mode((windowX, winwowY))
FPS = frame_rate
pygame.display.set_caption('Flappy Bird')
def drawObject():
display_surface.blit(background, (0, 0))
display_surface.blit(bird, (birdX, birdY))
def update():
pygame.display.update()
pygame.time.Clock().tick(FPS)
# Here is where define my global vars
def initializes():
global birdX, birdY, birdSpeedY
birdX = 60
birdY = 150
birdSpeedY = 0
initializes()
while True:
birdSpeedY += 1
birdY += birdSpeedY
drawObject()
update()
The message is telling you exactly what the issue is. The global variables aren't defined in global scope.
That means that for these variables that you are telling it you want to use from the global namespace global birdX, birdY, birdSpeedY, it expects to find a definition of those in that uppermost namespace. The global keyword does NOT create them in the global namespace just because you use it. They must exist there independent of that.
For them to be defined in the global scope there needs to be an assignment to them in the global namespace, not inside a function or a class. That cannot be something a += either since that is a reference and an assignment and so it assumes that the definition must be elsewhere (or it would be being referenced before a value was assigned).
So somewhere in the global namespace you need an assignment. If you want to handle the initialization in a function (as you are doing) it must still be defined/assigned outside that function, but it can be any value, like None. So you could add this near the top of you program:
birdX = None
birdY = None
birdSpeedY = None
Then still use your initializes() as you are.
Or in your case you would probably just take the stuff inside initializes() and put it at the top /global level.

Are there cases where global keyword is necessary in python?

I want to know if there are some cases where declaring global keyword is necessary in python.
Yes, there are some cases where global is neccessary.
Have a look at this code, which will work fine:
i = 42 # this is a global var
def f():
print(i)
But what if you would like to edit i (which is a global variable).
If you do this, you get an error:
i = 42 # this is a global var
def f():
i += 1 # this will not work
print(i)
We can only access i. If python compiles the function to bytecode it detects an assignment to a variable and it assumes it is a local variable. But this is not the case here (it is a global variable). Therefore if we also want to modify the global var i we must use the global keyword.
i = 42 # this is a global var
def f():
global i
i += 1 # this will change the global var without error
print(i)
When you have shared resources and want to make changes in global one.
a = 0
def add_five():
global a
a += 5
def remove_two():
global a
a -= 2
add_five() # a = 5
add_five() # a = 10
add_five() # a = 15
remove_two() # a = 13

Why is this variable not defined if it is a global variable?

I create a list and try to append it to another list, but even though it is a global list it still is not defined.
I had the same issue trying to apppend a string to another list, and that had the same error so I tried to make the string a list.
sees if the player hits
def hit_or_stand():
global hit **<-- notice hit is a global variable**
if hitStand == ("hit"):
player_hand()
card = deck()
hit = []
hit.append(card)
now I need to append hit to pHand (player's hand)
def player_hand():
global pHand
deck()
pHand = []
pHand.append(card)
deck()
pHand.append(card)
pHand.append(hit) **<--- "NameError: name 'hit' is not defined"**
pHand = (" and ").join(pHand)
return (pHand)
hit_or_stand()
player_hand()
global hit
This does not declare a variable which is global. It does not create a variable which does not exist. It simply says "if you see this name in this scope, assume it's global". To "declare" a global variable, you need to give it a value.
# At the top-level
hit = "Whatever"
# Or in a function
global hit
hit = "Whatever"
The only time you need a global declaration is if you want to assign to a global variable inside a function, as the name could be interpreted as local otherwise. For more on globals, see this question.
There is a misunderstanding of the global operation in OP's post. The global inside a function tells python to use that global variable name within that scope. It doesn't make a variable into a global variable by itself.
# this is already a global variable because it's on the top level
g = ''
# in this function, the global variable g is used
def example1():
global g
g = 'this is a global variable'
# in this function, a local variable g is used within the function scope
def example2():
g = 'this is a local variable'
# confirm the logic
example1()
print( g ) # prints "this is a global variable"
example2()
print( g ) # still prints "this is a global variable"

Python - UnboundLocalError: local variable "ID" referenced before assignment

Id, conf = recognizer.predict(gray[y:y+h,x:x+w]
def hour(cn):
for z in range(9,17):
if now.hour == z:
worksheet(cn, str(z)+":00")
def identify(number):
sht = gc.open("Test")
wks3 = sht.worksheet("NAMES")
b = wks3.acell('B'+str(number)).value
a = wks3.acell('A'+str(number)).value
if(Id == a and conf<65):
print(Id, conf)
Id = str(b)
Time = time.ctime()
hour(number)
elif(conf>64):
print(conf)
Id = "Unknown"
for m in range(2,100):
identify(m)
The above code is being used for facial recognition, I copied what I felt was necessary, it is not the entire code.
I'm trying create a function which I want to call back in a for loop
What am I doing wrong? I've been looking t this for 6 hours now, and anything I try doesn't seem to work.
I get a message back saying "UnboundLocalError: local variable 'Id' referenced before assignment"
It's impossible because I'm assigning with:
a = wks3.acell('A'+str(number)).value
So it grabs the ID number from the google spread sheet and checks if it is equaled to that, can someone tell me where I'm going wrong here?
def identify(number):
sht = gc.open("Test")
wks3 = sht.worksheet("NAMES")
b = wks3.acell('B'+str(number)).value
a = wks3.acell('A'+str(number)).value
#because you did, Id = ?
if(Id == a and conf<65):
print(Id, conf)
Id = str(b)
Time = time.ctime()
hour(number)
elif(conf>64):
print(conf)
Id = "Unknown"
Because you did, variable Id isn't passed as any parameter or global/local variable or as an argument to existing class.
If Id was parameter:
def identify(number,Id):
If Id was global variable:
def identify(number):
global Id
If Id was local variable:
def identify(number):
id = None # or some other data type
And if Id was argument from some class:
some_class.Id
In short you referenced Id before it was initialised. This is rookie mistake and there is some stuff where you can actually init a variable in if elif else statement but you need to trow a none of above logic of the rule.
if True: Id = 2; elif False: Id = 3; else: Id =0 #this is pseudocode, don't paste it in.
Also have in mind that next variable is also Unbound conf
EDIT:
Often to avoid this problem we write code like this:
def somefunction(parm1,parm2... ):
# global variables : description for variable stack is optional
global var1,var2 # if needed
#local variables
var3,var4 = None;
var5 = 'something else'
#in body functions : functions inside functions or just general program functions
def a(... ): return ...
#body : actually what function/program does.
# returning , finishing statement.

How to change global variables in Python [duplicate]

This question already has answers here:
Using global variables in a function
(25 answers)
Closed 3 years ago.
I am trying to change a variable further down the program. I have a global variable declared at the start of the program and I want to change the variable in different functions down the program. I can do this by declaring the variable inside the function again but I would like to know is there a better way of doing this. Some test code is below to explain what I mean.
ID = 'No'
project = ("Yep"+ID) # ID added with 'No' value which I later want to change
def pro():
ID = "YES"
print ID
def pro1(ID):
# I could declare project again to get this to work, but I would like to avoid this
print project # I want this to print with the new ID number.
if __name__ == '__main__':
pro()
pro1(ID)
Has anyone any ideas, thanks
I have tried the global variable but when I do this the project variable still prints out YepNo instead of YepYES. I want the new variable from the function proto change the variable in the project variable.
To update global variables you could use
global ID
ID="Yes"
before assigning variable to ID = "YES"
But changing ID will be no effect on project variable, project = ("Yep"+ID), because project is already a string
you need to make a function like
def getprojectname(ID):
return project+ID
The whole program may be like this
UPDATE:
... removed
Beware, you're doing it wrong multiple times.
Even though you could use the global statement to change a global (it is discouraged since it's better to use function parameters and return values), that would NOT change other already assigned values. E.g. even though you reassign ID, you would NOT reassign project. Also: your functions return nothing, there's no point in assigning a name to their return value, and it's a BAD habit using an all-uppercase name (ID) for a variable since it's a convention to use them for constants.
This should clarify you the way global works:
myid = ''
project = ("Yep"+myid) #ID added with no value which I later want to change
def mutate_id():
global myid
myid = "YES"
def mutate_project():
global project
project = ("YEP" + myid)
if __name__ == '__main__':
print "myid", myid
print "project ", project
print
mutate_id()
print "myid", myid
print "project ", project
print
mutate_project()
print "myid", myid
print "project ", project
print
But the best way is to do WITHOUT globals:
def get_new_id(old):
return "YES"
def get_new_project(old):
return ("YEP" + myid)
if __name__ == '__main__':
myid = ''
project = ("Yep"+myid)
print "myid", myid
print "project ", project
print
myid = get_new_id(myid)
print "myid", myid
print "project ", project
print
project = get_new_project(project)
print "myid", myid
print "project ", project
print
This will make all code interaction clear, and prevent issues related to global state change.
Use the global statement.
The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals.
Example: http://www.rexx.com/~dkuhlman/python_101/python_101.html#SECTION004340000000000000000
P.S.
But don't use global too often, see http://www.youtube.com/watch?v=E_kZDvwofHY#t=10m45
In your code you have two problems. The first about changing ID variable, which could be solved by using global.
The second that your code calculate project string and after that project don't know about ID.
To avoid code duplication you can define function to calc project.
So we have:
ID = 'No'
def GetProject():
return "Yep"+ID
def pro():
global ID
ID = "YES"
print ID
print GetProject()
pro()
print GetProject()
You can mutate without reassigning:
variables = {}
def pro():
if variables['ID'] == '':
variables['ID'] = 'default'
Why not use a dictionary?
>>> attr = {'start':'XXX', 'myid':'No'}
>>>
>>> def update_and_show(D, value = None):
... if value: D['myid'] = value
... print D['start'] + ' ' + D['myid']
...
>>> update_and_show(attr)
XXX No
>>> update_and_show(attr, 'Yes')
XXX Yes
>>> update_and_show(attr, 'No')
XXX No
>>>

Categories