Thursday, January 28, 2021

Python Morsels: Assigning to Global Variables

Transcript:

Let's talk about assigning to global variables in Python.

Variable assignments are local

Let's take a global variable (a variable defined outside of any function) called message:

>>> message = "Hello world"

And let's define a function called set_message that assigns to the message variable:

>>> def set_message(name):
...     message = f"Hello {name}"
...

If we call the set_message function with the name Trey, it will assign message to Hello Trey.

>>> set_message("Trey")

But if we read message now, it's not actually Hello Trey, it's Hello world:

>>> message
'Hello world'

This happens because assignments within a function only assign to local variables. So when we're inside set_message function, we're always assigning, to a local variable.

So that message variable in the set_message function is a local variable. When the function returns, that local variable disappears.

So calling set_message doesn't actually change our global variable message, it just shadowed the global variable message (meaning we made a local variable with the same name as a global variable).

The global variable promise: "I promise I will not assign to global variables from within a function"

It is actually possible in to write to global variables in Python.

I'm going to show you how to write to global variables, but you must promise me that you won't actually every do this.

Promised? Great! Read on...

Assigning to global variables

I've assigned to global variables (from within a function) very infrequently in my own Python code and you probably shouldn't do this in your code either. But Python does allow you to do this even though you often shouldn't.

The trick to writing a global variable is to use the global statement:

>>> def set_message(name):
...     global message
...     message = f"Hello {name}"
...

When we call this new set_message function you'll see that it actually updates the global message variable:

>>> set_message("Trey")
>>> message
'Hello Trey'

If we call set_message with a different name, message will change again:

>>> set_message("Guido")
>>> message
'Hello Guido'

Normally, all assignments assign to local variables and variables are either local or global in one scope. But you can think of the global statement as an escape hatch: it's a way of declaring that the message variable is a global variable within the set_message function.

Best practices with global variables

So, every time we read from it and (more importantly) every time we write to it, it should read from and write to the global variable message.

You don't need the global statement if you're just reading. Whenever you read a variable, Python will look for a local variable with that name and, if it doesn't find it, it will look for a global variable with the same name.

You only need global when you're writing to a global variable. And, you probably shouldn't be writing to global variables from within a function.

Functions are typically are seen as having inputs (which come from their arguments usually) and outputs (usually their return value).

Global state usually shouldn't be changed simply by calling a function. Functions usually provide information through their return value.

It's a common practice to make a function like this:

>>> def get_message(name):
...     return f"Hello {name}"
...

This get_message function doesn't assign to a message variable; it just returns a string which represents the message we actually want:

>>> get_message("Trey")
'Hello Trey'

This get_message function doesn't change our global variable message:

>>> message
'Hello world'

But if we did want to change our global message variable, as long as we're in the global scope when we're calling the function, we can assign to that global variable directly:

>>> message = get_message("Trey")

Assigning to message while at the module-level (outside of any function), changes the global message variable directly:

>>> message
'Hello Trey'

If we wanted to change it to something else, we'd pass in a different argument, and continue to assign to the message variable:

>>> message = get_message("Guido")
>>> message
'Hello Guido'

Typically in Python we embrace the fact that all assignments are local; unless you're in the global scope (you're outside of any function) because then assignment statements will assign to the global scope.

Summary

All assignments assign to local variables in Python, unless you use the global statement which is kind of our escape hatch for assigning to a global variable. Don't do it though! You don't usually want that escape hatch.

Typically instead of assigning to a global variable, you should return from your function and leave it up to the caller of your function to assign to a global variable, if they would like to.



from Planet Python
via read more

No comments:

Post a Comment

TestDriven.io: Working with Static and Media Files in Django

This article looks at how to work with static and media files in a Django project, locally and in production. from Planet Python via read...