How to define a global variable in Python

Learn to define global variables in Python. Explore methods, tips, real-world applications, and how to debug common errors.

How to define a global variable in Python
Published on: 
Thu
Feb 12, 2026
Updated on: 
Tue
Feb 24, 2026
The Replit Team Logo Image
The Replit Team

Global variables in Python let you share data throughout your program. The global keyword makes a variable accessible from any scope, which simplifies state management across different functions.

You'll learn techniques to define and modify global variables safely. You will also find practical tips, explore real-world applications, and get debugging advice to help you avoid common pitfalls and manage scope effectively.

Basic global variable definition

counter = 0

def increment():
   global counter
   counter += 1
   return counter

print(increment())
print(counter)--OUTPUT--1
1

The counter variable is initialized in the global scope, outside of any function. To modify it from within the increment() function, you must explicitly tell Python you're referencing the global version.

  • The global counter declaration is key. It prevents Python from creating a new, local counter variable that would exist only inside the function.
  • This statement ensures that the operation counter += 1 modifies the original variable defined at the top level of the script.

That's why calling the function and then printing counter separately both yield 1, confirming the global state was changed.

Common techniques for global variable management

Beyond the basic global statement, Python offers more structured methods for handling shared data, such as using separate modules or leveraging class variables.

Using the global keyword in functions

x = 10

def modify_global():
   global x
   x = 20
   print(f"Inside function: x = {x}")

print(f"Before function: x = {x}")
modify_global()
print(f"After function: x = {x}")--OUTPUT--Before function: x = 10
Inside function: x = 20
After function: x = 20

This example shows how the global keyword lets a function directly alter a variable in the global scope. Initially, x is 10. When modify_global() is called, it doesn't create a new local variable because of the global declaration.

  • The statement global x tells Python you intend to modify the existing global variable named x.
  • As a result, the assignment x = 20 changes the original variable's value, not a temporary local one.

The output confirms the change persists, as x remains 20 even after the function finishes running.

Using separate modules for global variables

# Save this as config.py
DATABASE_URL = "postgres://user:pass@localhost/db"
DEBUG = True
MAX_CONNECTIONS = 100

# In main.py
import config

print(f"Debug mode: {config.DEBUG}")
config.DEBUG = False
print(f"Debug mode updated: {config.DEBUG}")--OUTPUT--Debug mode: True
Debug mode updated: False

A cleaner way to manage global state is by creating a dedicated module, like config.py, to hold your variables. When you import this module into other files, you're essentially creating a single, shared namespace. This keeps your configuration settings organized and separate from your application logic, making your code much easier to maintain.

  • You can access and modify these variables using dot notation, such as config.DEBUG.
  • Any changes, like setting config.DEBUG = False, are immediately reflected across your entire program wherever the config module is imported.

Class variables as pseudo-globals

class AppConfig:
   VERSION = "1.0.0"
   API_KEY = "abc123"
   TIMEOUT = 30

print(f"App version: {AppConfig.VERSION}")
AppConfig.VERSION = "1.0.1"
print(f"Updated version: {AppConfig.VERSION}")--OUTPUT--App version: 1.0.0
Updated version: 1.0.1

Using a class to hold configuration data offers a structured alternative to true globals. The AppConfig class acts as a namespace, grouping related settings like VERSION and API_KEY together. It's a clean way to manage state without creating an object.

  • You can access and modify these class variables directly through the class name, such as AppConfig.VERSION.
  • This approach keeps your global-like variables organized and prevents them from polluting the global scope, making your code easier to read.

Advanced global variable patterns

As your program scales, you'll find more robust solutions in patterns like a global dictionary, the Singleton design, and thread-safe contextvars.

Using a global configuration dictionary

CONFIG = {
   "theme": "dark",
   "language": "en",
   "notifications": True
}

def toggle_notifications():
   CONFIG["notifications"] = not CONFIG["notifications"]
   return CONFIG["notifications"]

print(f"Notifications: {CONFIG['notifications']}")
print(f"After toggle: {toggle_notifications()}")--OUTPUT--Notifications: True
After toggle: False

A global dictionary like CONFIG offers a flexible way to manage related settings. Since dictionaries are mutable, you can modify their contents from within a function without needing the global keyword. Your function is changing the dictionary object itself, not reassigning the variable.

  • The toggle_notifications() function directly accesses and modifies the value for the notifications key inside the original CONFIG dictionary.
  • This pattern centralizes your configuration, making it easy to read and update multiple settings from anywhere in your code.

Managing globals with a Singleton pattern

class GlobalState:
   _instance = None
   
   def __new__(cls):
       if cls._instance is None:
           cls._instance = super().__new__(cls)
           cls._instance.counter = 0
       return cls._instance

state1 = GlobalState()
state2 = GlobalState()
state1.counter += 1
print(f"State1 counter: {state1.counter}")
print(f"State2 counter: {state2.counter}")--OUTPUT--State1 counter: 1
State2 counter: 1

The Singleton pattern ensures a class has only one instance, providing a single point of access to shared state. The GlobalState class controls object creation using the __new__ method. The first time you call GlobalState(), it creates a new object and saves it in _instance. Every subsequent call returns that same saved object.

  • This means state1 and state2 aren't two different objects; they both point to the exact same instance.
  • That’s why modifying state1.counter is immediately reflected when you check state2.counter—they share the same underlying data.

Thread-safe globals with contextvars

import contextvars

user_id = contextvars.ContextVar('user_id', default=None)

def set_user(id):
   user_id.set(id)

def get_user_info():
   return f"Processing data for user: {user_id.get()}"

set_user(42)
print(get_user_info())--OUTPUT--Processing data for user: 42

The contextvars module is perfect for concurrent applications, like web servers, where multiple tasks run at once. It lets you create variables that feel global but are safely isolated to a specific execution context—like a single user request. This prevents data from one thread from accidentally leaking into another.

  • You create a context variable using contextvars.ContextVar().
  • The set() method assigns a value within the current context, while get() retrieves it.
  • In this case, user_id is set to 42, which get_user_info() can access because they share the same context.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the global variable patterns we've explored, Replit Agent can turn them into production-ready tools:

  • Build an application with a centralized configuration module, allowing you to manage settings like API_KEY or DEBUG mode across the entire program.
  • Create a web service that uses a shared state, like a Singleton, to manage a connection pool or cache.
  • Deploy a simple API that tracks request counts using a global counter variable, providing real-time usage metrics.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser. Get started and turn your concepts into reality with Replit Agent.

Common errors and challenges

Working with global variables can introduce tricky bugs, but understanding a few common pitfalls makes them much easier to manage.

  • A simple typo in a variable name is a frequent source of a NameError. Python raises this error because it can't find a variable with that specific name in either the local or global scope, forcing you to hunt down a small mistake in your code.
  • Local variable shadowing occurs when a function creates a variable with the same name as a global one. Without the global keyword, Python assumes you want a new, separate variable, so any changes you make won't affect the original global state.
  • The difference between modifying and reassigning mutable globals like a dict is subtle. You can change a dictionary's contents from a function without any special keywords, but if you try to assign a whole new dictionary to the variable, you'll create a local variable instead—unless you explicitly declare global.

Debugging the NameError from typos in variable names

A NameError is a frequent roadblock, often caused by a simple typo. When you misspell a variable, Python can't find what you're referring to and stops execution. This error highlights a mismatch between the variable you defined and what you used.

See how this plays out in the following example, where a small spelling mistake inside the calculate_total function leads to a crash.

def calculate_total(items):
   # Misspelled variable name
   totel = sum(items)
   return total  # NameError: name 'total' is not defined

calculate_total([1, 2, 3])

The function calculates the sum and assigns it to totel, but then it tries to return a different variable, total. Since total was never defined, Python raises a NameError. See how a small change fixes the issue.

def calculate_total(items):
   total = sum(items)
   return total

print(calculate_total([1, 2, 3]))

The fix is straightforward: by correcting the typo, the variable name total is now used consistently for both the assignment and the return statement. This ensures the function can find and return the calculated value, resolving the NameError.

  • This kind of slip-up is common, especially in longer functions or when you're refactoring code.
  • A good linter or careful proofreading can help you catch these simple spelling mistakes before they cause a crash.

Understanding local variable shadowing with the same name

Without the global keyword, a function variable with the same name as a global one won't modify the original. Python treats it as a new, local variable, effectively "shadowing" the global one. This can be confusing, as the following code demonstrates.

message = "Global message"

def print_message():
   message = "Local message"
   print(message)

print_message()
print(message)  # Still "Global message"

The print_message() function defines its own message variable, which only exists locally. This change doesn't affect the global variable because it's "shadowed" inside the function. See how to explicitly modify the global state in the corrected code.

message = "Global message"

def print_message():
   global message
   message = "Updated global message"
   print(message)

print_message()
print(message)  # Now "Updated global message"

The fix is to declare global message inside the function. This tells Python you intend to modify the original variable, not create a new local one. As a result, the change to message persists outside the function's scope, updating the global state as intended.

  • This is a common solution when a function appears to have no effect on a global variable.
  • Use the global keyword anytime you need to reassign a global variable from within a function.

Fixing reassignment vs. modification of mutable dict globals

With a global dictionary like config, it's easy to fall into a common trap. While you can modify its contents directly, reassigning the entire variable inside a function creates a new, local dictionary, leaving the original untouched. The following code shows this mistake in action.

config = {"debug": False, "log_level": "INFO"}

def enable_debug():
   # This creates a new local dict instead of modifying global
   config = {"debug": True, "log_level": "DEBUG"}

enable_debug()
print(config)  # Still shows original values

The assignment inside enable_debug() doesn't alter the global config dictionary; it just creates a temporary, local one that's discarded. See how a simple adjustment ensures the function modifies the original dictionary as intended.

config = {"debug": False, "log_level": "INFO"}

def enable_debug():
   global config
   config = {"debug": True, "log_level": "DEBUG"}

enable_debug()
print(config)  # Shows updated values

The fix is to declare global config. This tells Python you intend to reassign the entire global dictionary, not just create a new, local one that gets discarded. Without it, your function's changes won't stick outside its scope.

  • Use the global keyword when replacing the whole dictionary.
  • You don't need it if you're only modifying a key's value, like config["debug"] = True. This distinction is crucial for managing mutable globals correctly.

Real-world applications

With the common errors out of the way, you can apply these patterns to practical uses like tracking application metrics or managing feature flags.

Using global for application metrics tracking

A global variable is a straightforward tool for keeping a running count of key application events, such as API requests and errors.

# Track API usage metrics
request_count = 0
error_count = 0

def process_api_request(endpoint, success=True):
   global request_count, error_count
   request_count += 1
   if not success:
       error_count += 1
   return f"Processed request to {endpoint}"

print(process_api_request("/users"))
print(process_api_request("/data", success=False))
print(f"Stats: {request_count} requests, {error_count} errors")

This example shows how request_count and error_count maintain a persistent state across function calls. The process_api_request() function can modify these variables because the global keyword tells Python to look outside the function's local scope, preventing it from creating new, temporary variables.

  • The request_count increases with every call, giving you a running total.
  • The error_count only goes up when the optional success parameter is set to False, letting you track failures separately.

Implementing feature flags with dict globals

A global dictionary provides a flexible way to manage feature flags, giving you a central place to turn application behaviors like dark_mode on or off dynamically.

# Global feature flags configuration
FEATURES = {
   "dark_mode": True,
   "beta_features": False,
   "max_upload_size": 10  # MB
}

def render_ui(username):
   theme = "dark" if FEATURES["dark_mode"] else "light"
   upload_limit = FEATURES["max_upload_size"]
   return f"Rendering {theme} UI for {username} with {upload_limit}MB upload limit"

print(render_ui("user123"))
FEATURES["dark_mode"] = False
print(render_ui("user123"))

The FEATURES dictionary acts as a global container for settings. Because dictionaries are mutable, their contents can be changed from anywhere in your program. The render_ui() function simply reads from this dictionary to configure its output without needing the global keyword.

  • The first call to render_ui() uses the initial "dark_mode": True setting.
  • Afterward, the line FEATURES["dark_mode"] = False directly modifies the global dictionary's value.
  • The second call reflects this update, showing how changes to a mutable global are immediately visible across your code.

Get started with Replit

Turn what you've learned into a real tool. Tell Replit Agent to "build a web app that tracks API requests with a global counter" or "create a settings module to manage feature flags for a user dashboard."

Replit Agent writes the code, tests for errors, and deploys your application. Start building with Replit and bring your ideas to life.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.