-1

Very simple problem (At least I think so): So I have a global variable, in this case test, and I want to assign an other value to it in a function. This is my code:

test = "Hello"

def launch():
    test = "F"

launch()
print(test)

I wanted test to equal "F", but it doesn't. Instead, the output of this is that test still equals "Hello". I assume it creates a variable inside the function and then assigns a value to it. But why does this work then:

test = {
    "?": "Hallo"
}

def launch():
    test["?"] = "F"

launch()
print(test)

The output of this is how I wanted it to be: test["?"] is equal to "F". How is this working and why isn't the first code example? Is there any way to use the first code how I wanted it to work?

by James
  • 89
  • 10
  • In the first case, you're trying to access a global variable but you have also redeclared it as a local variable. In second case,you're assigning to a global variable, not redeclaring it as a local variable. There in lies the difference. – LazyCoder Aug 01 '19 at 16:09
  • Check this tutorial for more examples https://www.python-course.eu/python3_global_vs_local_variables.php – sal Aug 01 '19 at 16:10
  • This actually has to do with the mutability of objects in Python. In the first case, the object test is immutable, so changes to `test` in your function creates a new local object. In the second case, the dictionary `test` is a mutable object, so alterations to it within a function stick. – h0r53 Aug 01 '19 at 16:13
  • @CaitLANJenner I don't think this has anything to do with mutability of the object. It likely has more to do with the fact that `test["?"] = "F"` is equivalent to `test.__setItem__("?", "F")`, and that only makes sense if `test` already exists. I would expect the same behavior in the first case even if `test` was mutable. Unless you're talking about reassignment vs mutation of the object. – Carcigenicate Aug 01 '19 at 16:20
  • Possible duplicate of [Using global variables in a function](https://stackoverflow.com/questions/423379/using-global-variables-in-a-function) – DavidW Aug 02 '19 at 14:10

5 Answers5

2

You need to add a global test line to the top of the function to tell it to reference an existing variable instead of creating a new one. It's ambiguous otherwise.


Why does the second one work though? Because it isn't ambiguous. From context, it knows that you must be referencing an existing variable instead of attempting to create a new one.

test["?"] = "F"

is essentially

test.__setItem__("?", "F")

and that only makes sense if test already exists. It knows that you aren't trying to create a new local variable.

The language only requires a global test statement in cases where it can't tell whether or not you want to use an existing variable or create a new one.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
0

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, however, it’s assumed to be a local unless explicitly declared as global.

So, change it as follows:

test = "Hello"

def launch():
    global test
    test = "F"
jarmod
  • 71,565
  • 16
  • 115
  • 122
  • 2
    With the exception of mutable objects. In the second example the `test` dictionary is mutable and thus alterations to it do not result in creating a new object and the changes hold globally. – h0r53 Aug 01 '19 at 16:15
0

In your second example you don't declare the dictionary (like test = {}). Hence, python looks for a global variable test. You can access global variables by:

def launch():
    global test
    test = "F"
Carsten
  • 2,765
  • 1
  • 13
  • 28
0

In the first case, you're trying to access a global variable but you have also redeclared it as a local variable.

test = "Hello" #global variable by default.

def launch():
    test = "F" # local variable by default. It's restricted to the function launch().

launch()
print(test) # Accessing global variable because print can't see test of launch.
test = "Hello" #global variable by default.

def launch():
    global test
    test = "F" # Accessing global value of test.

launch()
print(test) # Accessing global variable test.

In second case,you're assigning to a global variable, not redeclaring it as a local variable. There in lies the difference.

test = {'?':"Hello"} #global variable by default.

def launch():
    test['?'] = "F" # global variable access by default. It's NOT restricted to the function launch().

launch()
print(test) # Accessing global variable.
LazyCoder
  • 1,267
  • 5
  • 17
0

In your first test, in your launch function, the test variable is recreated, with no link to the global function. It's a particularity of python.

If you wanted to change the global function you should have done like this :

def launch():
   global test
   test = 'F'

With your second test, test is a dictionary.

And yes, when you change a dictionary in a function without declaring it as a global variable, it changes the dictionary outside of the function as well.

If you want to know the real reason, it's way more complicated if you don't know C language... Python was programmed in C (for CPython at least), and in C, managing variables is very different than in Python.

In C, when you want to modify a variable in a function, you have to give to the function the memory address of the variable as a parameter (that variable is called a Pointer).

If you don't give the pointer of your global variable to the function where you want to modify it, it won't work.

When your launch function was called in your first example, test wasn't modified, because as you haven't declared test as global, python hasn't given the pointer of test to the launch function (only its value).

When you use dictionaries, Python will also give the value of the dictionary, but it will be a pointer to its elements. So you will be able to modify them.

That's why you can modify the elements in the dictionary, but you can't modify the dictionary. Example :

a = {"a":123, 'b':456}
def modif():
    a = {"aa":123}
modif()
print(a)

results in:

{'a': 123, 'b': 456}

So the dictionary hasn't been modified. It works the same way with the lists (and I suppose with every iterable that support item assignment)

I tried to simplify, it's more complicated in reality, but it may teach you some thing I hope.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Alex_6
  • 259
  • 4
  • 16