Are Globals in Python Really Global?

Author:Murphy  |  View: 28126  |  Time: 2025-03-23 12:00:31

PYTHON PROGRAMMING

Truly global means accessible from everywhere. Photo by Markus Spiske on Unsplash

Does Python offer globals?

An immediate response is, it does. And indeed, enough to look into the Python official documentation to read that…

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, it's assumed to be a local unless explicitly declared as global.

So, Python definitely offers globals. What's more, globals constitute quite a controversial topic, as using them can lead to serious difficulties for both the developer and the user.

You might think, why at all should we use a Programming tool that is so controversial. It's a fair question – but it's simple to answer. Globals are among programming tools that can be very useful under the condition that they are correctly used. Incorrectly used, however, they can do more harm than good.

Globals are among programming tools that can be very useful under the condition that they are correctly used. Incorrectly used, however, they can do more harm than good.

Globals can be accessed from anywhere in a program. Hence, if you need a particular object to be accessible from everywhere – this is when you create a global object.

You can create global constants, which don't change during program execution; and global variables, which can change. A global constant is thus a literal value. Examples can be, for instance, a company's name, the value of Pi, or any mathematical constant. A global variable can be price, demand or color; these values can change, and that's why they are variables.

The Python naming convention for globals is as follows: use uppercase for global constants (PI) and lowercase for global variables (price).

Globals constitute a typical topic in programming, but this does not have to mean that they work the same in each programming language. Globals in Python have their own specificity, and any Python developer must know how they work.

In this article, therefore, we'll discuss what makes the essence of global variables: the global scope. I will show you what global means in the Python context, and that what we normally consider global in Python does not necessarily mean truly global.

We'll also analyze the implications of this issue – and I'll show you how to utilize this knowledge in coding practice. This will require knowledge, skills and – above all – caution, because these are quite subtle matters that can easily lead to significant mistakes.

What is a global variable?

This article does not aim to debate whether globals should be used or not. It's enough to say that a global variable has a global scope and its value can change, while a global constant has a global scope and its value cannot change.

Let's postpone the discussion of whether or not you should use globals in your Python programs for another day. First, it is such an important topic that it deserves our full attention, and therefore deserves a dedicated article. Second, to discuss things like that, we need to know more about the global scope in Python, a topic that this article introduces.

Globals generally

As Tony Gaddis explains in his book, a global variable can be used in all modules in a program. In other words, the global scope is the entire program, so a global variable or constant can be used in each module of the program.

This is a very concise explanation, but that's all we need because there is nothing complex about the definition of global variables.

Globals in Python

You will see that the definition of globals in Python is more complicated. Interestingly, the official Python documentation doesn't say much about globals. You can read the small section I linked to above, and you can read about the global statement itself. You should also note the following digression in PEP8, where the style guide explains the naming convention for global variables:

Let's hope that these variables are meant for use inside one module only.

In other words, let's hope that global variables are meant for use at the module level, not at the truly global level.

The question is, do you know how to use global objects that are truly global in Python? In the following section, I will show you what they are and how to make objects global across the entire program. Such objects are available in this particular Python session from any module without having to import them, just like sum, list and many other objects are available without actually importing them.

Module global scope

A module global scope is what the name suggests: the global scope for a particular module. It's best to show this in an example:

# module_scopes.py

# define globals
COMPANY_NAME = "The Global Bindu Company"
year = 2023

# use globals in a function
def represent():
    return f"{COMPANY_NAME} in {year}"

Okay, so what do we have here? First of all, we've got two global objects:

  • COMPANY_NAME – a global constant
  • year – a global variable

Then we have a function represent(), which uses both of these globals. Let's see this in action:

>>> import module_scopes
>>> module_scopes.represent()
The Global Bindu Company in 2023
>>> module_scopes.year = 2024
>>> represent()
The Global Bindu Company in 2024

What you've just seen is the typically understood global scope in Python: the module global scope. It's time to move on, to discuss the program global scope.

Program global scope

The only global variables in Python that can be accessed from all modules are those available in the builtins module.

It contains, for instance, the above-mentioned sum and list objects as well as many others, such as exceptions (e.g., ValueError or Exception) or various functions (e.g., any or all). So, basically anything that is available through the builtins module is available in all the modules in the Python session.

Now, for our little hack. It's quite simple, so if you're not new to Python, you might have already come up with it yourself. If you want to make an object global, simply add it to the builtins module. This will immediately make the object available in all the modules of a session without the need to import anything. Of course, we're talking about a particular session, the one in which the object has been added to the builtins scope.

If you want to make an object global, it's enough to add it to the builtins module.

Let's see how this trick works. First, create a main.py module:

# main.py

import builtins

builtins.SCREAM = "SCREAM!!!"

Now create another module, use.py, located in the same directory:

# use.py

def scream(n: int) -> str:
    return SCREAM * n

As you can see, the scream() function uses the SCREAM object, even though it's neither defined nor imported in the use module. What we do know, however, is that it's defined and added to the builtins module in the main module. Will this work?

First, note that Pylance will not like using the SCREAM object inside the use module:

Pylance doesn't know that SCREAM has been added to builtins. Screenshot from Visual Studio Code, by author

Neither will [mypy](https://mypy.readthedocs.io/en/stable/):

[Mypy](https://mypy.readthedocs.io/en/stable/) doesn't know that SCREAM has been added to builtins. Screenshot from Visual Studio Code, by author

So, this is considered a static error. Is it?

It is – even if we can make this work dynamically. This is a static error because whether or not this will work depends on the order of imports. If you simply import use and run the scream() function, you will get an error:

The failure of use.scream(2): SCREAM is undefined. Screenshot from Visual Studio Code, by author

However, if you first import main and then use, you may be surprised to see the scream() function working just fine:

Success of use.scream(2): SCREAM has been added to builtins. Screenshot from Visual Studio Code, by author

This time, it worked because when we imported main, these lines were run:

The builtins hack: SCREAM is now a truly global object. Screenshot from Visual Studio Code, by author

That way, the builtins module achieved a new object, SCREAM. From now on, you can use SCREAM:

The builtins hack: SCREAM is now a truly global object. Screenshot from Visual Studio Code, by author

Conclusion

In the article, I showed you a little hack to make Python objects truly global. You've unlikely seen this method in action, but this doesn't mean it's completely unused.

One example is the [tracemem](https://github.com/nyggus/tracemem/) Python package. In its documentation, you will see the following explanation of why tracemem utilizes the builtins global scope:

Since this feature of tracemem is to be used to debug memory use from various modules, it'd be inconvenient to import the required objects in all these modules. That's why the required objects are kept in the global scope…

Whether you find this explanation convincing or not, I believe it's valuable to be aware of this trick. It's one of those things that can significantly broaden your Python knowledge by helping you grasp the language's intricacies.

However, the decision of whether or not to use builtins globals in your coding practice is a different story. Of one thing I am certain: you should never decide to do so without a solid understanding of how globals operate in Python.

I called this a hack, but never forget that all Python objects available in a session are made available via the builtins globals. This doesn't mean, however, that you should use this method for any global: any global is not the same thing as Python builtins.

Thus, you definitely shouldn't overuse this hack. Not only can it introduce static and dynamic errors, but also it can makes code difficult to read and comprehend. However, in rare instances, you might find yourself thinking that despite these drawbacks, this is precisely what you need.

If that's the case, pause and reconsider your decision. Then, reconsider it again. And even once more. Discuss it with your fellow project members. Only after this thorough evaluation, if no one raises objections, should you consider using this method.

Regardless of whether or not you ever employ this concept in your own projects, it's essential to grasp how the builtins scope and globals function. This is because the builtins scope establishes the fundamental scope of Python, and without understanding this you will never really know how Python works.


Thanks for reading. If you enjoyed this article, you may also enjoy other articles I wrote; you will see them here. And if you want to join Medium, please use my referral link below:


Join Medium with my referral link – Marcin Kozak

Tags: Data Science Getting Started Programming Python Python Object

Comment