jin
jin

Reputation: 31

Wrapping global variables in a class (python)

I'm new to programming, and have recently learned python and the basics of object oriented programming. I'm aware that having lots of global variables is generally a bad idea, and that I can put them all into a class instead. Is this the right way to do it?

class GameState(object):
    def __init__(self):
        self.variable1 = 1
        self.variable2 = 2
        self.list = [3, 4, 5]

g_state = GameState()

And, if I wish to access the variables within g_state, what is the best way to go about doing it?

Pass g_state into the functions/classes that need access? Implement getters and call those? Use g_state.variable1 directly?

Or is there a better way?

EDIT: To be more specific, I'm trying to write a game in python using pygame, and was thinking of putting my gamestate variables into a class so as to not have a bunch of global variables lying around. I'm unsure of how to access those variables with good design so I don't run into trouble later.

Upvotes: 3

Views: 8046

Answers (4)

Kugel
Kugel

Reputation: 19864

You are right that too many global variables is not a good idea. Polluted global namespace may lead to errors.

However, don't put them into class for the sake of it. If you have really that many variables maybe you should consider splitting your program into multiple modules.

Also please understand that you can't really crate global variables in Python like you can in JavaScript. Your variables are always scoped under the module.

Let me illustrate with an example. Module a.py:

A = 42

Module b.py:

import a

print(A)

What do you get? NameError. Why? because variable A is not global, it is under module a. You need to use a.A to reference it.

There is no need to stuff variables under class. They are under modules, which acts as a namespace, and there is nothing wrong with it.

Upvotes: 5

Rubens
Rubens

Reputation: 14778

NO!!! Building a VariableBox will help you NOT!

Simply use the var you want, wherever it may applies. If you have too many global vars, it's rather a problem with what should be considered global, and what should pertain to specific structures. Or even a difficulty in naming the vars, or creating arrays, instead of var1, var2, var3, ....

Classes are designed for building of objects, i. e., for creating things that differ for specificities, but have the same basis. A valuable class is something that somewhat defines an entity, and the main behaviors of this entity.

EDIT:

Python does not provide visibility constraints, so you won't be able to protect data by simply stuffing it into a class; the entries can be accessed from any place an instance of the class is.

Creating getters or simply maintaining an instance of a class is just a matter of deciding which one to work with. For the sake of maintaining things clear, it may be better to make a controller to your game, that will make this interface between game assets and gameplay.

For example, during execution, you could have:

class Controller:

    def __init__():
        self.turn = 0
        self. ...

    def begin():
        self.turn += 1
        self.opening_scene()

class Gameplay:

    def __init__(self, num_players, turn, ...):
        self.turn = turn # if it happens you want to use this value in the game
        self.num_player = num_players

# Main loop
controller = Controller()
controller.num_players = int(raw_input("Number of players: "))

gameplay = Gameplay(controller.num_players, controller.turn)
while True:

    if gameplay.action == ...:
    elif ...:
        ...
    elif *next turn*:
        controller.next_turn() # to set things up to next turn
    else ...:
        ...

Inside Controller you may aggregate correlated info, so you won't have an endless list of parameters in the upcoming functions.

Anyway, I'm not capable of telling you which is the best to use; there are lots of people that study these modularity issues, and I'm not one of them, so this is just my point of view on what could work out nice on your app.

Upvotes: 1

jdi
jdi

Reputation: 92617

Creating a class simply for storing variables is not necessary. A class would only be needed if you really do need multiple instances of that class, each with unique values.

But for a single global state, a dictionary object can suffice for this purpose. You can store it in a module specifically intended for config and state if you want:

conf.py

GAME_STATE = {
    'level': 0,
    'score': 0,
    'misc': [1,2,3],
}

main.py

import conf

conf.GAME_STATE['score'] = 100

So your other modules can just import the conf.py module and access the state dict. You can store whatever types you need in this object. It also gives you a convenient location to add functionality for serializing these values out to disk if you want, and reading them back at future runs of the program, and to keep them alongside configuration options.

Upvotes: 2

Peter Schneider
Peter Schneider

Reputation: 1701

There are two ways to access the variables: one global object or passing an instance to a function. The first one is a bad idea too in general. The second one is better. But do not create a single object with all variables! (see the first comment).

There are more things to consider if you pass around an object. A good idea is implementing things as a member-function if suitable.

class VariableBox(object):
    def __init__(self):
        self.variable1 = 1
        self.variable2 = 2
        self.list = [3, 4, 5]

    def do_something(self):
        self.variable1 = self.variable2 + 42
        return self.variable1

Upvotes: 2

Related Questions