[Python]#15 @Decorator

Jude's Sound Lab·2025년 1월 23일

Algorithm & Coding

목록 보기
5/5

Decorator

Why Does decorated "funcion" Automatically Pass to the Decorator?

The decorator system in Python is built to pass the function being decorated (unstable_function) automatically to the decorator. This is part of the Python syntax for decorators. Here’s how it works:

  • When you define a decorator like this:
def my_decorator(func):
    ...

And use it as @my_decorator, Python internally rewrites it to:

func = my_decorator(func)
  • So if you want to use additional arguments
@retry(max_retries=3, delay=1)
def unstable_function():
    ...
unstable_function = retry(max_retries=3, delay=1)(unstable_function)

Example

Without arguments

def logging_decorator(func):
    # The decorator receives the original function as an argument
    def wrapper(*args, **kwargs):
        # This is the replacement function (the wrapper)
        print(f"Function {func.__name__} was called with arguments {args} and {kwargs}")
        result = func(*args, **kwargs)  # Call the original function
        return result  # Return its result
    return wrapper  # Return the wrapper function itself

@logging_decorator
def multiply(x, y):
    return x * y

# Step-by-step:
# multiply = logging_decorator(multiply)
# Now `multiply` is actually `wrapper`.

result = multiply(4, 5)
# This calls `wrapper(4, 5)`.
# Inside `wrapper`:
# - It logs: "Function multiply was called with arguments (4, 5) and {}"
# - Calls the original `multiply(4, 5)`
# - Returns the result (20)

print(result)  # Output: 20

With arguments--Outer function

How It Works

  1. Outer Function (retry):
    Accepts max_retries and delay as arguments.
    Returns the actual decorator (decorator).

  2. Decorator Function (decorator):
    Accepts the target function (func) as an argument.
    Returns the wrapper.

  3. Wrapper Function (wrapper):
    Contains the retry logic.
    Tries to execute the target function up to max_retries times.
    Prints messages for failed attempts and retries.
    Raises an exception if all attempts fail.

import random
import time

def retry(max_retries=3, delay=1):
    def decorator(func):
        def wrapper(*args, **kwargs):
            attempts = 0
            while attempts < max_retries:
                try:
                    return func(*args, **kwargs)  # Try to execute the function
                except Exception as e:
                    attempts += 1
                    print(f"Attempt {attempts} failed with error: {e}. Retrying...")
                    time.sleep(delay)  # Optional delay between retries
            raise RuntimeError(f"Function failed after {max_retries} retries.")
        return wrapper
    return decorator
@retry(max_retries=3, delay=2)
def unstable_function():
    if random.random() < 0.7:  # 70% chance of failing
        raise ValueError("Something went wrong!")
    print("Success!")

# Call the function
unstable_function()
profile
chords & code // harmony with structure

0개의 댓글