Richard210363
Richard210363

Reputation: 8406

Why does my module not behave like a singleton?

I have a JSON file that I am using as a datastore in a small game I am using as a way to learn Python.
I am proficient in a number of other languages.

I have several classes that want read access to the JSON so I want to load the JSON from the file into a variable and then allow the other classes to access the variable via getters and setters, because each class wants different parts of the JSON.

This sounds like a job for a Singleton. I understood that a Python Module behaves like a singleton.

However, when I import the Module into my classes the variable resets?

Here is a very cut down example:

Module:- state_manager

x=45
def set_x(value):
    x=value

def get_x():
    return x

Class:- Game

import Player

import state_manager
value = state_manager.get_x()

Class:- Player

import state_manager
state_manager.set_x(12)

By setting breakpoints I can see that when Player is imported by Game that Player sets the value of x in state_manager to 12.

But when I look at the value of x returned to Game using state_manager.get_x() I get 45.

Why is this?

What is the correct way in Python to create a Module or Object that can be shared among other classes?

I realise I can construct a Singleton myself but I thought I'd use the features of Python.

Upvotes: 3

Views: 83

Answers (2)

Tom Karzes
Tom Karzes

Reputation: 24052

You need to declare x global in any function that attempts to set it globally:

def set_x(value):
    global x
    x=value

Without the global declaration, x is just a function-local variable.

In general, if a function assigns to a variable, anywhere in the function, then that variable is local unless it is explicitly declared global (or nonlocal). If a function only reads a variable, without setting it, then the variable is taken from a higher scope (e.g., a global, or an up-level reference).

Upvotes: 2

Dolda2000
Dolda2000

Reputation: 25855

By setting breakpoints I can see that when Player is imported by Game that Player sets the value of x in state_manager to 12.

I am fairly sure that you're doing something wrong in your inspection, because the set_x function, at least as you quoted it...

x=45
def set_x(value):
    x=value

...does not do what you think it does. Since x is being assigned to in the scope of set_x, it does not refer to the global (module-level) variable x, but to a local variable x that is immediately discarded as part of the stack frame when set_x returns. The existence of static assignments is effectively how local variables are declared in Python. The fix is to declare x as referring to the global variable:

x=45
def set_x(value):
    global x
    x=value

Upvotes: 3

Related Questions