Welcome to Python closures! A closure is a powerful feature where an inner function remembers variables from its outer scope, even after the outer function has finished executing. In this example, the inner function captures the variable x from the outer function's scope.
Here's how closures work step by step. First, we call the outer function with an argument. The outer function creates an inner function that references the outer function's parameter. When the outer function returns the inner function, that parameter value is captured and remembered. Even after the outer function finishes, the returned function still has access to that captured value.
Here's a practical example of closures in action. This counter function demonstrates how closures can maintain state. Each time we call make_counter, it creates a new closure with its own count variable. The increment function captures and modifies this count variable. Notice how counter1 and counter2 maintain separate counts - each closure has its own independent state.
Let's summarize the key points about Python closures. First, the inner function can access variables from the outer function's scope. These variables are captured by reference, not copied. Each closure instance maintains its own independent state. The captured variables remain in memory as long as the closure exists. Finally, use the nonlocal keyword when you need to modify captured variables. Closures provide an elegant way to create functions with persistent state and encapsulated behavior in Python!
Here's how closures work step by step. First, we call the outer function with an argument. The outer function creates an inner function that references the outer function's parameter. When the outer function returns the inner function, that parameter value is captured and remembered. Even after the outer function finishes, the returned function still has access to that captured value.
Here's a practical example of closures in action. This counter function demonstrates how closures can maintain state. Each time we call make_counter, it creates a new closure with its own count variable. The increment function captures and modifies this count variable. Notice how counter1 and counter2 maintain separate counts - each closure has its own independent state.
Let's summarize the key points about Python closures. First, the inner function can access variables from the outer function's scope. These variables are captured by reference, not copied. Each closure instance maintains its own independent state. The captured variables remain in memory as long as the closure exists. Finally, use the nonlocal keyword when you need to modify captured variables. Closures provide an elegant way to create functions with persistent state and encapsulated behavior in Python!
Here's an advanced closure example using a decorator. The timer decorator function returns a wrapper function that captures the original function in its closure. When called, the wrapper measures execution time and prints it. This demonstrates how closures enable powerful patterns like decorators, where we can modify or extend function behavior without changing the original code. The closure captures both the original function and any variables from the decorator's scope, creating flexible and reusable code patterns.