Go Here to Read this Fast! This lock is about to unlock a major iOS 18 UWB feature
Originally appeared here:
This lock is about to unlock a major iOS 18 UWB feature
Go Here to Read this Fast! This lock is about to unlock a major iOS 18 UWB feature
Originally appeared here:
This lock is about to unlock a major iOS 18 UWB feature
Originally appeared here:
Ring is giving two of its best security cameras a free video-quality upgrade this week
Originally appeared here:
This new Kidde Ring Smoke Alarm might be just what my smart home is looking for
Originally appeared here:
Intel announces new Core Ultra 200 series mobile CPUs at CES 2025, targeting enthusiasts and edge users
Go Here to Read this Fast! Amazon is bringing its satellite broadband to the UK
Originally appeared here:
Amazon is bringing its satellite broadband to the UK
Go Here to Read this Fast! Samsung Galaxy S25 price rumors: how much is the S25 line likely to cost?
Originally appeared here:
Samsung Galaxy S25 price rumors: how much is the S25 line likely to cost?
When you’re deep in rapid prototyping, it’s tempting to skip clean scoping or reuse common variable names (hello, df!), thinking it will save time. But this can lead to sneaky bugs that break your workflow.
The good news? Writing clean, well-scoped code does not require additional effort once you understand the basic principles.
Let’s break it down.
Think of a variable as a container that will store some information. Scope refers to the region of your code where a variable is accessible.
Scope prevents accidental changes by limiting where variables can be read or modified. If every variable was accessible from anywhere, you’ll have to keep track of all of them to avoid overwriting it accidentally.
In Python, scope is defined by the LEGB rule, which stands for: local, enclosing, global and built-in.
Let’s illustrate this with an example.
# Global scope, 7% tax
default_tax = 0.07
def calculate_invoice(price):
# Enclosing scope
discount = 0.10
total_after_discount = 0
def apply_discount():
nonlocal total_after_discount
# Local scope
tax = price * default_tax
total_after_discount = price - (price * discount)
return total_after_discount + tax
final_price = apply_discount()
return final_price, total_after_discount
# Built-in scope
print("Invoice total:", round(calculate_invoice(100)[0], 2))
Variables inside a function are in the local scope. They can only be accessed within that function.
In the example, tax is a local variable inside apply_discount. It is not accessible outside this function.
These refer to variables in a function that contains a nested function. These variables are not global but can be accessed by the inner (nested) function. In this example, discount and total_after_discount are variables in the enclosing scope of apply_discount .
The nonlocal keyword:
The nonlocal keyword is used to modify variables in the enclosing scope, not just read them.
For example, suppose you want to update the variable total_after_discount, which is in the enclosing scope of the function. Without nonlocal, if you assign to total_after_discount inside the inner function, Python will treat it as a new local variable, effectively shadowing the outer variable. This can introduce bugs and unexpected behavior.
Variables that are defined outside all functions and accessible throughout.
The global statement
When you declare a variable as global inside a function, Python treats it as a reference to the variable outside the function. This means that changes to it will affect the variable in the global scope.
With the global keyword, Python will create a new local variable.
x = 10 # Global variable
def modify_global():
global x # Declare that x refers to the global variable
x = 20 # Modify the global variable
modify_global()
print(x) # Output: 20. If "global" was not declared, this would read 10
Refers to the reserved keywords that Python uses for it’s built-in functions, such as print , def , round and so on. This can be accessed at any level.
Both keywords are crucial for modifying variables in different scopes, but they’re used differently.
Variable shadowing happens when a variable in an inner scope hides a variable from an outer scope.
Within the inner scope, all references to the variable will point to the inner variable, not the outer one. This can lead to confusion and unexpected outputs if you’re not careful.
Once execution returns to the outer scope, the inner variable ceases to exist, and any reference to the variable will point back to the outer scope variable.
Here’s a quick example. x is shadowed in each scope, resulting in different outputs depending on the context.
#global scope
x = 10
def outer_function():
#enclosing scope
x = 20
def inner_function():
#local scope
x = 30
print(x) # Outputs 30
inner_function()
print(x) # Outputs 20
outer_function()
print(x) # Outputs 10
A similar concept to variable shadowing, but this occurs when a local variable redefines or overwrites a parameter passed to a function.
def foo(x):
x = 5 # Shadows the parameter `x`
return x
foo(10) # Output: 5
x is passed as 10. But it is immediately shadowed and overwritten by x=5
Each recursive call gets its own execution context, meaning that the local variables and parameters in that call are independent of previous calls.
However, if a variable is modified globally or passed down explicitly as a parameter, the change can influence subsequent recursive calls.
Let’s illustrate this with an example.
counter = 0 # Global variable
def count_up(n):
global counter
if n > 0:
counter += 1
count_up(n - 1)
count_up(5)
print(counter) # Output: 5
counter is a global variable shared across all recursive calls. It gets incremented at each level of recursion, and its final value (5) is printed after the recursion completes.
def count_up(n, counter=0):
if n > 0:
counter += 1
return count_up(n - 1, counter)
return counter
result = count_up(5)
print(result) # Output: 5
Avoid vague names like df or x. Use descriptive names such as customer_sales_df or sales_records_df for clarity.
This is the standard naming convention for constants in Python. For example, MAX_RETRIES = 5.
Global variables introduces bugs and makes code harder to test and maintain. It’s best to pass variables explicitly between functions.
What’s a pure function?
Using nonlocal or global would make the function impure.
However, if you’re working with a closure, you should use the nonlocal keyword to modify variables in the enclosing (outer) scope, which helps prevent variable shadowing.
A closure occurs when a nested function (inner function) captures and refers to variables from its enclosing function (outer function). This allows the inner function to “remember” the environment in which it was created, including access to variables from the outer function’s scope, even after the outer function has finished executing.
The concept of closures can go really deep, so tell me in the comments if this is something I should dive into in the next article! 🙂
If you need to refer to an outer variable, avoid reusing its name in an inner scope. Use distinct names to clearly distinguish the variables.
That’s a wrap! Thanks for sticking with me till the end.
Have you encountered any of these challenges in your own work? Drop your thoughts in the comments below!
I write regularly on Python, software development and the projects I build, so give me a follow to not miss out. See you in the next article 🙂
Why Variable Scoping Can Make or Break Your Data Science Workflow was originally published in Towards Data Science on Medium, where people are continuing the conversation by highlighting and responding to this story.
Originally appeared here:
Why Variable Scoping Can Make or Break Your Data Science Workflow
Go Here to Read this Fast! Why Variable Scoping Can Make or Break Your Data Science Workflow
Is C is faster than Rust? I had always assumed the answer to that question to be yes, but I recently felt the need to test my assumptions.
Originally appeared here:
Measuring The Execution Times of C Versus Rust
Go Here to Read this Fast! Measuring The Execution Times of C Versus Rust