Global variables declared within function are still considered local - python

I am trying to write the program battleship. I have two gameboard matrices: one for player, one for computer. These are defined outside of main because I want them to be global variables because several functions manipulate/read them. I am using Python 2.6.1.
#create player game board (10x10 matrix filled with zeros)
playerBoard = [[0]*10 for i in range(10)]
#create computer game board (10x10 matrix filled with zeros)
computerBoard = [[0]*10 for i in range(10)]
Then I define the main function.
#define main function
def main():
global playerBoard
global computerBoard
#keepGoing is true
keepGoing = True
#while keepGoing is true
while keepGoing:
#call main menu function. Set to response.
response = mainMenu()
#if response is 1
if response == "1":
#begin new game
#call clearBoards function
clearBoards()
#call resetCounters function
resetCounters()
#call placeShips function (player)
playerBoard = placeShips(playerBoard, "player")
#call placeShips function (computer)
computerBoard = placeShips(computerBoard, "computer")
#call guessCycler function
guessCycler()
#if response is 2
if response == "2":
#keepGoing is false
keepGoing = False
Despite my declaration of global playerboard and global computerBoard within main PyScripter still says those are local variables. I don't understand this. How can I make sure they are global?
Documents I have already looked at:
Using global variables in a function other than the one that created them
Changing global variables within a function
http://www.python-course.eu/global_vs_local_variables.php

I definitely think you should reconsider if you need them to be global - You don't .-)
The cheap way, is do declare your stuff and the pass them on as parameters to the function
def MyFunc(board1):
print board1
board1 = "Very weak horse"
MyFunc(board1)
The real way to do it is to create a class and then access them using self
class MySuperClass():
def __init__(self):
self.horse = "No way up"
def myRealCoolFunc(self):
print self.horse
uhhh = MySuperClass()
uhhh.myRealCoolFunc()

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.

Passing the updated value of a variable between modules

I have two modules in pygame. One (game_manager) in charge of creating the game and all the activities you can do there. Another (window_manager) in charge of updating the game window and drawing all the elements.
While refactoring the code to create new game modes I ran into a problem.
I want to pass a variable DECK_PLAYER from game_manager to window_manager:
# IN GAME_MANAGER.py
TABLERO = []
DECK_PLAYER = []
<some code>
def set_tablero(size):
global TABLERO
global DECK_PLAYER
TABLERO = class_board.crear_tablero(size)
DECK_PLAYER = class_cards.create_decks()
def get_deck_player():
global DECK_PLAYER
print("get_deck_player() -> ", DECK_PLAYER)
return DECK_PLAYER
if __name__ == "__main__":
board_size = 3
CLOCK.tick(30)
set_tablero(board_size)
print("get_deck_player() -> ", get_deck_player())
game_init()
both of the prints so far print the correct result, DECK_PLAYER as a list with elements. But if I call
# IN WINDOW_MANAGER.py
deck_p = game_manager.get_deck_player()
print(deck_p)
this print returns an empty list ([]), and I don't understand why. Shouldn't get_deck_player return the current value of the variable?
SOLVED IT:
as I was running game_manager as main, the call from window_manager should be:
import __main__
deck_p = __main__.get_deck_player()
to get the correct value of the variable

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"

How do I pass variables around in Python?

I want to make a text-based fighting game, but in order to do so I need to use several functions and pass values around such as damage, weapons, and health.
Please allow this code to be able to pass "weapons" "damage" "p1 n p2" throughout my code. As you can see I have tried using parameters for p1 n p2, but I am a little bit a newbie.
import random
def main():
print("Welcome to fight club!\nYou will be fighting next!\nMake sure you have two people ready to play!")
p1=input("\nEnter player 1's name ")
p2=input("Enter player 2's name ")
print("Time to get your weapons for round one!\n")
round1(p1,p2)
def randomweapons(p1,p2):
weapon=["Stick","Baseball bat","Golf club","Cricket bat","Knife",]
p1weapon=random.choice(weapon)
p2weapon=random.choice(weapon)
print(p1 +" has found a "+p1weapon)
print(p2 +" has found a "+p2weapon)
def randomdamage():
damage=["17","13","10","18","15"]
p1damage=random.choice(damage)
p2damage=random.choice(damage)
def round1(p1,p2):
randomweapons(p1,p2)
def round2():
pass
def round3():
pass
def weaponlocation():
pass
main()
There are a few options.
One is to pass the values as parameters and return values from your various functions. You're already doing this with the names of the two players, which are passed as parameters from main to round1 and from there on to randomweapons. You just need to decide what else needs to be passed around.
When the information needs to flow the other direction (from a called function back to the caller), use return. For instance, you might have randomweapons return the weapons it chose to whatever function calls it (with return p1weapon, p2weapon). You could then save the weapons in the calling function by assigning the function's return value to a variable or multiple variables, using Python's tuple-unpacking syntax: w1, w2 = randomweapons(p1, p2). The calling function could do whatever it wants with those variables from then on (including passing them to other functions).
Another, probably better approach is to use object oriented programming. If your functions are methods defined in some class (e.g. MyGame), you can save various pieces of data as attributes on an instance of the class. The methods get the instance passed in automatically as the first parameter, which is conventionally named self. Here's a somewhat crude example of what that could be like:
class MyGame: # define the class
def play(self): # each method gets an instance passed as "self"
self.p1 = input("Enter player 1's name ") # attributes can be assigned on self
self.p2 = input("Enter player 2's name ")
self.round1()
self.round2()
def random_weapons(self):
weapons = ["Stick", "Baseball bat", "Golf club", "Cricket bat", "Knife"]
self.w1 = random.choice(weapons)
self.w2 = random.choice(weapons)
print(self.p1 + " has found a " + self.w1) # and looked up again in other methods
print(self.p2 + " has found a " + self.w2)
def round1(self):
print("Lets pick weapons for Round 1")
self.random_weapons()
def round2(self):
print("Lets pick weapons for Round 2")
self.random_weapons()
def main():
game = MyGame() # create the instance
game.play() # call the play() method on it, to actually start the game

local variable 'door_open' referenced before assignment

I am very new to python. I am trying to learn by making a text based game.
In the gameplay I am wanting a variable, door_open, to begin false but once unlocked door_open = True. The next time the function is called a different message would be displayed.
door_open =False
def house():
print "The door is locked"
plan = raw_input(">")
if plan.lower() == 'use key':
inventory.remove("House Key")
door_open = True
print "You are inside"
start() ## this just returns to the starting point outside
if door_open == True:
print "You walk inside"
exit(0) ## using this until I develop it more
else:
print "Door is locked. Do you want to use your key (Y/N)?"
When Python sees an assignment to a variable in a function, when the variable is not marked as global (or nonlocal), it treats the variable as a new local variable.
Thus Python is treating the original code similarly to
door_open = False
def house():
if plan.lower() == 'use key':
door_open_LOCAL = True # only assigned here
if door_open_LOCAL == True: # whoops, might not be assigned yet!
pass
(That is, the local variable shadows the global variable, I've emphasized the point above by giving the local variable a different name entirely.)
See also:
Why some Python variables stay global, while some require definition as global
Use of "global" keyword in Python
If you want to write to a variable in the global scope you need to use the global keyword:
door_open = False
def house():
global door_open
print "The door is locked"
# ...
Also, please read and follow PEP8, the Python style guide. For example. you shouldn't use if foo == True: but if foo:
You are trying to track status of your game and got a bit lost in where is the status noted:
This is typical situation for using a class:
game.py:
import sys
class Game():
def __init__(self):
self.door_open = False
self.inventory = ["House Key", "Snow Gun", "Swiss army knife"]
def unlock_house(self):
assert "House Key" in self.inventory, "`House Key` must be present in inventory"
self.inventory.remove("House Key")
print "Click, Click"
self.door_open = True
def fireup(self):
print "Bufff"
self.inventory = []
def main():
game = Game()
while True:
# report current status
if game.door_open:
print "You are in the house!"
print "You are the King"
sys.exit(0)
else:
print "The door is locked!"
# ask for further plans
print "What is your further plan?"
plan = raw_input(">")
# change the situation
if plan.lower() == "use key":
game.unlock_house()
elif plan.lower() == "set up file":
game.fireup()
if __name__ == "__main__":
main()
You can see the split between the class Game, which is able to track the status and even do some changes of it, and the main piece of code, where you try to use the game somehow.
The class Game is sort of idea, how your notes about game status could look like.
Then in game = Game() you instantiate the class, get an object, and start doing real changes to the status.
Having status information stored in well designed and quite well isolated object is very convenient, you know, where to find what you need.

Categories