Python Forum
Global variables not working
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Global variables not working
#1
I have made some global variables. A simplified version of the program (but with the same rationale) is this:

sentence_1 = "hello"
sentence_2 = "hello"

class MyClass:
    def __init__(self, parent = None):
        # do something
        function_A()
        function_B()

        def function_A:
            # do something ...
            global sentence_1 = "new string 1"

        def function_B:
            # do something ...
            global sentence_2 = "new string 2"
The problem I face is that although I use, or not use the word global, the sentence_1 and sentence_2, they do not change, but the initial strings "hello" remain. Do I miss something here?
Reply
#2
Why do you want global mutable things in the first place? That leads to code that's hard to follow and maintain.
hobbyist likes this post
Reply
#3
(Jan-15-2021, 01:04 PM)ndc85430 Wrote: Why do you want global mutable things in the first place? That leads to code that's hard to follow and maintain.

So, you imply return variables of each function?
Reply
#4
(Jan-15-2021, 01:16 PM)hobbyist Wrote: So, you imply return variables of each function?

Let's start by saying you have SyntaxErrors in your code. Then, if it was just functions it's better to take arguments and then return the result.

Because it is a supposedly class (i.e. OOP) you can add and use attributes. But before that you need to fix the structure of your class (e.g. make the functions methods, not nested functions inside __init__() method. And if the functions don't need access to instance or class, you should ask yourself does it really belong to the class.

This makes it easier to debug and test your code, reuse it and so on.
(Jan-15-2021, 12:55 PM)hobbyist Wrote: Do I miss something here?
Also, what you have here is just the class definition, you never instantiate your class so that it execute (after you fix the multiple problems)

So this work, but it's BAD code and you should not do it:

sentence_1 = "hello"
sentence_2 = "hello"
 
class MyClass:
    def __init__(self, parent = None):
        # do something

        def function_A():
            # do something ...
            global sentence_1
            sentence_1 = "new string 1"
 
        def function_B():
            # do something ...
            global sentence_2
            sentence_2 = "new string 2"

        function_A()
        function_B()


spam = MyClass()
print(sentence_1)
print(sentence_2)
hobbyist likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
Do you understand what global does? Do you understand the concept of scope?

You can think of scope as a kind of dictionary that stores names. When you use a variable Python searches for the name in these scope dictionaries. Every function has a scope. Every module (file) has a scope. Python has a scope. The scopes even have names; Local for the function scope, Global for the module scope, and Built-in for the Python scope. There is an additional scope called Enclosing which occurs if you define functions inside of functions.

When you use a variable in your code Python searches for the variable in these scopes. The order of the search is Local, Enclosing, Global, Built-in. If you read about scope you may see this order referred to as LEGB. This is why ndc85430 asked why you are using the global keyword to use a mutable variable. Global variables are visible for use in any function defined in the module. However ndc85430 is wrong about "sentence_1" being mutable. "sentence_1" is a string, and strings are not mutable in Python.

When you assign a variable in your code Python creates the variable in the current scope. If your function uses the "global" keyword to declare the variable, the assignment creates the variable in the global scope. Your code would work if you got the syntax correct.
        def function_A:
            # do something ...
            global sentence_1
            sentence_1 = "new string 1"
You would know this if you ever bothered to read the Python documents before using new language features. If all your learning is focused on tutorials or looking at examples you risk never learning about how things work and why they work this way. The Python documents explain how a language feature fits into the Python puzzle. If you start reading the docs not only will you have fewer questions, but you will get a deeper understanding of Python and grow an intuition about why something is not working.

buran's suggestion about using attributes is a good one. In a class not only can you think of a scope as being a dictionary, it is a dictionary in the literal sense. An attribute is a variable defined in the context of the class. You use a special syntax to access these variables. From inside the class you use "self.name" to access the "name" attribute. From outside the class you use "instance.name" where "instance" is the name of a variable that references an instance of the class.
class MyClass:
    def __init__(self):
        """Use docstring notation instead of # as the header comment"""
        self.sentence_1 = "Hello"
        self.sentence_2 = "World"
 
    def function_A(self):
        # do something ...
        self.sentence_1 = "Goodnight"
 
    def function_B(self):
        # do something ...
        self.sentence_2 = "moon"

    def __repr__(self):
        return f'{self.sentence_1} {self.sentence_2}!'

a = MyClass()
print(a)
print(a.sentence_1)
print(a.sentence_2)
a.sentence_2 = 'sun'
print(a)
a.function_A()
a.function_B()
print(a)
The most useful thing about classes is that each instance gets their own namespace that they carry around wherever they go. If I create another instance of MyClass and assigned to the variable "b", I now have two instances of the class that are independent of each other. Changing attributes in "a" does not affect the corresponding attribute in "b". This is something that would be very difficult to do using just functions and modules.
Output:
Hello World! Hello World Hello sun! Goodnight moon!
hobbyist and Fuzzy like this post
Reply
#6
@deanhysted, in order to make it more versatile, you can pass initial values for attributes in the __init__()
hobbyist likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#7
No, I'm perfectly aware that strings aren't mutable. I was referring to the fact that variables can be reassigned.
hobbyist likes this post
Reply
#8
Then I am confused by your comment "Why do you want global mutable things in the first place?" The OP contained global strings which are immutable. I thought the mistake odd for you but see no other way to interpret the comment.
hobbyist likes this post
Reply
#9
(Jan-15-2021, 03:05 PM)deanhystad Wrote: Do you understand what global does? Do you understand the concept of scope?

You can think of scope as a kind of dictionary that stores names. When you use a variable Python searches for the name in these scope dictionaries. Every function has a scope. Every module (file) has a scope. Python has a scope. The scopes even have names; Local for the function scope, Global for the module scope, and Built-in for the Python scope. There is an additional scope called Enclosing which occurs if you define functions inside of functions.

When you use a variable in your code Python searches for the variable in these scopes. The order of the search is Local, Enclosing, Global, Built-in. If you read about scope you may see this order referred to as LEGB. This is why ndc85430 asked why you are using the global keyword to use a mutable variable. Global variables are visible for use in any function defined in the module. However ndc85430 is wrong about "sentence_1" being mutable. "sentence_1" is a string, and strings are not mutable in Python.

When you assign a variable in your code Python creates the variable in the current scope. If your function uses the "global" keyword to declare the variable, the assignment creates the variable in the global scope. Your code would work if you got the syntax correct.
        def function_A:
            # do something ...
            global sentence_1
            sentence_1 = "new string 1"
You would know this if you ever bothered to read the Python documents before using new language features. If all your learning is focused on tutorials or looking at examples you risk never learning about how things work and why they work this way. The Python documents explain how a language feature fits into the Python puzzle. If you start reading the docs not only will you have fewer questions, but you will get a deeper understanding of Python and grow an intuition about why something is not working.

buran's suggestion about using attributes is a good one. In a class not only can you think of a scope as being a dictionary, it is a dictionary in the literal sense. An attribute is a variable defined in the context of the class. You use a special syntax to access these variables. From inside the class you use "self.name" to access the "name" attribute. From outside the class you use "instance.name" where "instance" is the name of a variable that references an instance of the class.
class MyClass:
    def __init__(self):
        """Use docstring notation instead of # as the header comment"""
        self.sentence_1 = "Hello"
        self.sentence_2 = "World"
 
    def function_A(self):
        # do something ...
        self.sentence_1 = "Goodnight"
 
    def function_B(self):
        # do something ...
        self.sentence_2 = "moon"

    def __repr__(self):
        return f'{self.sentence_1} {self.sentence_2}!'

a = MyClass()
print(a)
print(a.sentence_1)
print(a.sentence_2)
a.sentence_2 = 'sun'
print(a)
a.function_A()
a.function_B()
print(a)
The most useful thing about classes is that each instance gets their own namespace that they carry around wherever they go. If I create another instance of MyClass and assigned to the variable "b", I now have two instances of the class that are independent of each other. Changing attributes in "a" does not affect the corresponding attribute in "b". This is something that would be very difficult to do using just functions and modules.
Output:
Hello World! Hello World Hello sun! Goodnight moon!

Many thanks, it finally works!!

Also thanks to everyone else who responded and helped me !!
Reply
#10
And one thing that has been talked around but not sure if it has been pointed out directly - it is generally a very bad idea for a function in a class to directly access data that is outside of the class. If you were to try to reuse the class by importing into a different file, there could be serious confusion about the errors that arise.
hobbyist likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Global vs. Local Variables Davy_Jones_XIV 4 555 Jan-06-2021, 10:22 PM
Last Post: Davy_Jones_XIV
  Global - local variables Motorhomer14 11 862 Dec-17-2020, 06:40 PM
Last Post: Motorhomer14
  Global not working why? Milfredo 13 1,498 Oct-06-2020, 02:37 AM
Last Post: Milfredo
  Question regarding local and global variables donmerch 12 1,671 Apr-12-2020, 03:58 PM
Last Post: TomToad
  local/global variables in functions abccba 6 1,107 Apr-08-2020, 06:01 PM
Last Post: jefsummers
  Where to put the global keyword when assigning variables outside a function? new_to_python 8 1,095 Feb-09-2020, 02:05 PM
Last Post: new_to_python
  Please help me understand how to use global variables joew 6 1,273 Jan-05-2020, 06:03 PM
Last Post: joew
  Global Variables - Some Points Needing Clarification. adt 4 1,210 Nov-30-2019, 01:23 PM
Last Post: adt
  modifying variables in local or global space Skaperen 2 758 Aug-14-2019, 07:13 AM
Last Post: Skaperen
  Global variable does not seem to be global. Columbo 6 1,478 Jul-15-2019, 11:00 PM
Last Post: Columbo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020