2
def initColors():
   BLACK = (0,0,0)  
   RED = (255,0,0)
   BLUE = (0,0,255)
   LIGHTGRAY = (128,128,128)
   DARKGRAY = (64,64,64)
   WHITE = (255,255,255)
initColors()
def initOtherVars():
   nhover = WHITE
   hover = RED
   mselected = BLACK
   selected = RED
initOtherVars()

I want it to set the value of nhover to the value of WHITE, but I get this error:

Traceback (most recent call last):
   File "C:\Users\jarr3\Desktop\Python\Battlr\battlrSelectionScreen1.py", line 30, in <module>
initOtherVars()
   File "C:\Users\jarr3\Desktop\Python\Battlr\battlrSelectionScreen1.py", line 27, in initOtherVars
      nhover = WHITE
NameError: name 'WHITE' is not defined

It seems that a variable cannot be assigned to the value of a variable that is defined in a function in a function, even if the first function is called before the second one is even defined. Why is this? And is there a different way to accomplish what I'm trying to do. (Besides just not using functions, I would like to keep using functions.) Thanks.

jpp
  • 159,742
  • 34
  • 281
  • 339
Purkat
  • 21
  • 3

2 Answers2

1

Python has scopes. Variables are only known inside scopes. You can define variables global to force them to be available in a global scope, but that clutters it and it is bad practice.

More on that, see Short Description of the Scoping Rules?.

You can make yours global:

def initColors():
    # declare them global
    global BLACK,RED,BLUE,LIGHTGRAY,DARKGRAY,WHITE
    BLACK = (0,0,0)  
    RED = (255,0,0)
    BLUE = (0,0,255)
    LIGHTGRAY = (128,128,128)
    DARKGRAY = (64,64,64)
    WHITE = (255,255,255)

initColors()

def initOtherVars():
    # need to be global as well, else invalid outside this scope 
    global nhover,hover,mselected,selected
    nhover = WHITE
    hover = RED
    mselected = BLACK
    selected = RED

initOtherVars()

Going this way you first have to put the colors into the global space and then also your other variables.


You could create a class that holds your colors as class-variables, which makes it accessable over Classname.Varname:

class MyColors:
   BLACK = (0,0,0)  
   RED = (255,0,0)
   BLUE = (0,0,255)
   LIGHTGRAY = (128,128,128)
   DARKGRAY = (64,64,64)
   WHITE = (255,255,255)

def initOtherVarsByClass():
    # these need still to be made global
    global Cnhover,Chover,Cmselected,Cselected
    Cnhover = MyColors.WHITE
    Chover = MyColors.RED
    Cmselected = MyColors.BLACK
    Cselected = MyColors.RED

initOtherVarsByClass()

But you still need to make your other variables global to have access to those you defined in your function. I think it would be easier to make a class as "holder" and create your mselected etc. in it to be accessed over the class.

class LinkColors():
    nhover = MyColors.WHITE
    hover = MyColors.RED
    mselected = MyColors.BLACK
    selected = MyColors.RED

You could as well create functions that simply return your color:

def GetSelected(): 
    return MyColors.RED

Instead of cluttering the global space you get more classes.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
1

The scope of initcolors() is different to to scope of initOtherVars(). You could create one function which includes all your variables.

Or, if you wish to have two separate objects, you can consider object-oriented programming and feed an instance of one class to another. For example:

class initColors():
    def __init__(self):
        self.BLACK = (0, 0, 0)
        self.RED = (255, 0, 0)
        self.WHITE = (255, 255, 255)

MyColors = initColors()

class initOtherVars(initColors):
    def __init__(self, color_class):
        self.nhover = color_class.WHITE
        self.hover = color_class.RED
        self.mselected = color_class.BLACK
        self.selected = color_class.RED

MyOtherVars = initOtherVars(MyColors)

print(MyOtherVars.nhover)  # (255, 255, 255)
jpp
  • 159,742
  • 34
  • 281
  • 339