Kodeclik Blog
How to resolve Python variable and function name conflicts
Sometimes you might create a Python program where both a function and variable are given the same name and this can give rise to some peculiarities.
In Python, using a variable with the same name as a function leads to issues because the name in the symbol table gets overridden. Here's an example to demonstrate how such a mistake can mess up a program and how you can fix it.
Example 1: Fixing Function Name Conflicts
Consider the below program:
def greet():
print("Hello, world!")
# Variable with the same name as the function
greet = "This is a string now!"
# Attempting to call the function
try:
greet()
except TypeError as e:
print(f"Error: {e}")
Note that we have a function called greet() and then a variable called greet.
If you run this program you will get:
Error: 'str' object is not callable
Here, the greet function is overridden by a string variable. When you attempt to call greet(), Python raises a TypeError because greet is no longer a function.
We can fix this by explicitly restoring the original function. When Python creates variables or functions it stores references to them in the globals() dictionary, which represents the current symbol table for the script. In the above case, the symbol table corresponding to greet() is over-ridden, hence the problem.
Here is how you can fix the program:
# Step 1: Define the function
def greet():
print("Hello, world!")
# Step 2: Store the original function explicitly in globals()
globals()['original_greet'] = greet
# Step 3: Override the function with a variable
greet = "This is a string now!"
# Step 4: Restore the function using the globals() table
greet = globals()['original_greet']
# Step 5: Call the restored function
greet()
This code demonstrates how to use Python's globals() table to manipulate and restore a function after its name has been overridden. Initially, the greet function is defined to print "Hello, world!" and its reference is saved in the global symbol table under the key 'original_greet' using globals(). This ensures that the function's reference is preserved, even if the greet name is reassigned.
Next, the greet name is overridden with a string, replacing the original function reference in the global symbol table. At this point, trying to call greet() would result in an error because greet now points to a string, which is not callable. However, by retrieving the original function reference from globals()['original_greet'] and assigning it back to greet, the function is effectively restored.
Finally, calling greet() successfully prints "Hello, world!" because the name greet once again points to the original function. This illustrates the utility of the globals() table for managing symbol table conflicts and preserving access to overridden objects in Python.
The output will be:
Hello, world!
as expected.
Example 2: Clearing a variable with globals()
Consider the below program:
# Step 1: Define a function
def greet():
print("Hello from the greet function!")
# Step 2: Override the function name with a variable
greet = "This is a string now!"
# Step 3: Clear the variable from the global scope
del globals()['greet'] # Remove the variable 'greet' from the symbol table
# Step 4: Redefine or access the original function
def greet():
print("Hello from the greet function, restored!")
# Step 5: Call the function
greet()
This program demonstrates how to resolve a naming conflict when a variable overrides a function name by using the globals() table. Initially, a greet function is defined, but its name is later overridden by a string variable, effectively replacing the function reference in the global symbol table. To fix this, the del globals()['greet'] statement removes the greet entry from the global symbol table, clearing the conflicting variable and making the name greet available again. After this, the greet function is redefined to restore its original purpose.
When the function is called, it works as expected because the conflict has been resolved:
Hello from the greet function, restored!
This illustrates how globals() can be used to directly manipulate the global symbol table and handle naming conflicts in Python.
Below are two more examples of symbol table manipulation to resolve conflicts caused by using the same name for variables and functions.
Example 3: Overriding a Built-in Function
Python provides many built-in functions, such as max(). Overriding these with variables can cause issues:
# Overriding a built-in function
max = [1, 2, 3]
# Attempting to use max() as a function
try:
result = max([4, 5, 6])
except TypeError as e:
print(f"Error: {e}")
The output will be:
Error: 'list' object is not callable
To fix this error, we can use the __builtins__ module to access the original built-in function and restore it.
# Overriding a built-in function
max = [1, 2, 3]
# Restore the original max function
max = __builtins__.max
# Use the restored max function
result = max([4, 5, 6])
print(f"The maximum value is: {result}")
The output will be:
The maximum value is: 6
Example 4: Local Scope vs Global Scope Conflict
In Python, a variable in the local scope can overshadow a global variable or function with the same name.
# Global function
def square(x):
return x * x
def calculate():
# Local variable with the same name
square = 5
try:
result = square(3) # Attempt to call the function
except TypeError as e:
print(f"Error: {e}")
calculate()
The output will be:
Error: 'int' object is not callable
Again, to fix this, we can use the globals() dictionary to explicitly access the global square function.
# Global function
def square(x):
return x * x
def calculate():
# Local variable with the same name
square = 5
# Explicitly access the global square function
global_square = globals()['square']
# Use the global function to calculate the square
result = global_square(square)
print(f"The square is: {result}")
calculate()
This code demonstrates how to resolve a naming conflict between a local variable and a global function using the globals() table. The global square function calculates the square of a number. Inside the calculate function, a local variable square is defined with the value 5, overriding the name square and making the global function inaccessible by its original name.
To bypass this conflict, the global square function is explicitly retrieved using globals()['square'] and assigned to the variable global_square. This ensures the original function is accessible despite the local naming conflict. The global_square function is then called with the value of the local variable square (5), with the result printed as "The square is: 25". This code illustrates the use of the globals() table to access global symbols when shadowed by local variables.
The output will be:
The square is: 25
Summary
Enjoy this blogpost? Want to learn Python with us? Sign up for 1:1 or small group classes.