0

I would like to have a variable that is common to many functions so I thought about using a global variable but I saw that it was a bad idea and that it's better to work with a class so I guess we should use a class attribute?

The real question is how can I go from a program that relies on a global variable to a program that uses a class attribute?

Let's say for example I have the following :

function.py :

my_variable = []

def function1():
    global my_variable
    #then we do something on my_variable
def function2():
    global my_variable
    #then we do something on my_variable

views.py (in flask) :

from function import my_variable
@app.route('/'):
    global my_variable 
    function1()
    function2()
    return my_variable 

I guess with a class we would have something like this for function.py ?

class Function:

    my_variable = []
    def __init__(self, variable):
        Function.my_variable = variable
    def function1(self):
    #we do something on Function.my_variable
    def function2(self):
    #we do something on Function.my_variable

Is this a good start ?

Draga
  • 23
  • 9
  • `Function.my_variable = variable` is a serious antipattern since it creates *global state*, the same for `global my_variable`s, etc. – Willem Van Onsem Nov 27 '17 at 12:54
  • "*Is this a good start?*" Yes. Is this a good practice? Probably not. Good luck following the value/state of `Function.my_variable` while debugging. – DeepSpace Nov 27 '17 at 12:54
  • Where did you read that it's better to have a class? It still has to be in the global namespace to make use of it. – roganjosh Nov 27 '17 at 12:55
  • 1
    It is good to minimize the use of globals, but having a couple of _mutable_ globals that you only mutate and _never_ assign to isn't so bad. With those, you don't need a `global` statement in the functions that mutate the global variable's contents, that's only needed if you want to perform an assignment to a global name. – PM 2Ring Nov 27 '17 at 12:57
  • Having global state is especially problematic in a web app like Flask, as you will almost certainly have multiple users. Are you sure you want the state to be shared across all users? – Daniel Roseman Nov 27 '17 at 13:01
  • Then how can I improve it? I posted a small program on a forum and someone told me that using a global variable isn't the best idea, I looked it up on the internet and I found sources that shared the same idea. @Daniel Roseman I don't know, I am still a beginner so I am trying to find a solution to my problem, my web app works with 5 files on the disk and I should be able to add, delete or modify entries in the files. The global variable was supposed to be used to get a file's content and from then I work on/with it to influence a file's content. – Draga Nov 27 '17 at 13:29

1 Answers1

1

As regards the pro's and con's of why globals are so evil in Python, I'm going to refer you to the following page that I used myself when researching this very thing a while ago:

Why are global variables evil?

What I find interesting is that I am using a Python linter in Visual Studio Code (my IDE of choice) and this linter always highlights globals as being a problem even when implemented correctly. Between the linter errors and the advice in the link that I shared, I followed the same rule you've already mentioned. Use class variables instead of global ones in Python.

As for how to make your global variables into class variables? It's quite straightforward.

So what you have above is a module where you're declaring your my_variable and initialising it as an empty list. So in a class, you can do the same thing as follows:

class MyClass:

    def __init__(self):
        self.my_variable = []

Or if you want to assign the value to the variable directly when you instantiate an instance of this class, you can also do the following:

class MyClass:

    def __init__(self, my_variable):
        self.my_variable = my_variable

So now you can create an instance of your MyClass by using:

myClass = MyClass() #For the first example OR
myClass = MyClass([]) #For the second example

So now we want to change the values of the my_variable part of MyClass so lets do that. You can pretty much use the same function style as you're used to from your global variables for this. Just note that in order to re-assign my_variable to a new value within the class, you'll need to use the self keyword when referring to it, since it now belongs to a class, as follows:

def function1(self):
    self.my_variable = #Change the value of my_variable

def function2(self):
    self.my_variable = #Change the value of my_variable again

So your entire class now looks like this:

class MyClass:

    def __init__(self):
        self.my_variable = []

    def function1(self):
        self.my_variable = #Change the value of my_variable

    def function2(self):
        self.my_variable = #Change the value of my_variable again

So now you've converted your global variable to a class variable but how can we use it? First, lets assume that your class MyClass is stored in a file called my_class.py. Going by your Flask method example, you now do the following:

from my_class import MyClass

    @app.route('/'):
        myClass = MyClass() 
        myClass.function1()
        myClass.function2()
        return myClass.my_variable

And this will work exactly as you need it to!

AJC24
  • 3,280
  • 2
  • 19
  • 30