w3resource
w3resource logo

Understanding Python Closures: Concepts and Practical Examples

(追記) (追記ここまで)
(追記) (追記ここまで)

Introduction to Python closures Functions

Closures in Python are a powerful feature that allows a function to retain access to its enclosing scope's variables even after the outer function has finished execution. Closures are used to create functions with some pre-configured behavior, making them particularly useful in decorators and callback functions. This tutorial will focus on examples to help you understand how closures work with maximum practical code.

Example 1: Basic Closure Example

This example demonstrates a basic closure, where an inner function retains access to variables from its enclosing function even after the outer function has completed.

Code:

def outer_function(msg):
 # Outer function that takes a message as an argument
 def inner_function():
 # Inner function that references the outer function's variable
 print(msg)
 return inner_function # Return the inner function
# Create a closure
closure = outer_function("Hello, World!")
# Call the closure
closure() # Output: Hello, World! 

Explanation:

  • Outer Function: 'outer_function()' defines a local variable 'msg' and an inner function 'inner_function()' that accesses msg.
  • Returning the Inner Function: The outer function returns 'inner_function()' without executing it.
  • Closure: When we call 'closure()', it still has access to 'msg', even though 'outer_function()' has finished executing.

Example 2: Closure with a Counter

This example shows how closures can maintain state between function calls, demonstrated by a simple counter that remembers its value.

Code:

def make_counter():
 # Outer function that initializes a counter
 count = 0
 def increment():
 # Inner function that increments the counter
 nonlocal count
 count += 1
 return count
 return increment # Return the inner function
# Create a counter closure
counter = make_counter()
# Call the counter multiple times
print(counter()) # Output: 1
print(counter()) # Output: 2
print(counter()) # Output: 3

Explanation:

  • Outer Function: 'make_counter()' initializes a variable count and defines an inner function 'increment()' that modifies count.
  • 'nonlocal' Keyword: 'nonlocal' is used to modify the count variable in the enclosing scope.
  • Closure: The counter closure maintains its own count state across multiple calls.

Example 3: Customizing Functions with Closures

This example demonstrates how closures can create customized functions, such as a multiplier, that carry specific behavior based on the outer function's arguments.

Code:

def multiplier(factor):
 # Outer function that takes a factor
 def multiply(number):
 # Inner function that multiplies a number by the factor
 return number * factor
 return multiply # Return the inner function
# Create closures with different factors
double = multiplier(2)
triple = multiplier(3)
# Use the closures
print(double(5)) # Output: 10
print(triple(5)) # Output: 15

Explanation:

  • Outer Function: 'multiplier()' takes a 'factor' and defines an inner function 'multiply()' that multiplies a given number by this factor.
  • Closures: The 'double' and 'triple' closures are customized functions that multiply numbers by 2 and 3, respectively.

Example 4: Closures as Decorators

This example illustrates how closures can be used as decorators, adding additional functionality (like logging) to existing functions without modifying their code.

Code:

def logger(func):
 # Outer function that takes a function as an argument
 def log_wrapper(*args, **kwargs):
 # Inner function that logs the function call and then executes it
 print(f"Calling {func.__name__} with arguments: {args}, {kwargs}")
 return func(*args, **kwargs)
 return log_wrapper # Return the inner function
# Applying the closure as a decorator
@logger
def add(x, y):
 return x + y
# Call the decorated function
print(add(3, 4)) # Output: Calling add with arguments: (3, 4), {}
 # 7

Explanation:

  • Outer Function: 'logger()' takes a function as an argument and defines an inner function 'log_wrapper()' that adds logging behavior.
  • Decorator: The 'log_wrapper()' closure logs the call details and then calls the original function.
  • Using the Closure: The 'add()' function is decorated with the 'logger' closure, so it logs its arguments whenever it is called.

Example 5: Closures for Data Encapsulation

This example demonstrates using closures for data encapsulation, creating an account with operations that securely manage the balance without exposing it directly.

Code:

def account(initial_balance):
 # Outer function that initializes balance
 balance = initial_balance
 def get_balance():
 # Inner function to get the balance
 return balance
 def deposit(amount):
 # Inner function to deposit money
 nonlocal balance
 balance += amount
 return balance
 def withdraw(amount):
 # Inner function to withdraw money
 nonlocal balance
 if amount <= balance: balance -= amount return balance else: return "Insufficient funds" # Return a dictionary of functions for encapsulated operations return {"get_balance": get_balance, "deposit": deposit, "withdraw": withdraw} # Create an account closure my_account = account(100) # Perform operations print(my_account["get_balance"]()) # Output: 100 print(my_account["deposit"](150)) # Output: 250 print(my_account["withdraw"](200)) # Output: 50 

Explanation:

  • Data Encapsulation: The 'account()' function encapsulates the balance and provides controlled access via closures.
  • Operations: The closures ('get_balance', 'deposit', 'withdraw') manipulate and access the balance securely without exposing it directly.
  • Using the Closures: Operations on the account are performed using the returned closures, ensuring data encapsulation.

PREV : Python Map, Filter and Reduce Functions
NEXT :Python Decorators

Test your Python skills with w3resource's quiz



Follow us on Facebook and Twitter for latest update.

(追記) (追記ここまで)


(追記) (追記ここまで)
(追記) (追記ここまで)


AltStyle によって変換されたページ (->オリジナル) /