---
title: "Explain the Python Decorators"  
description: "Explain the Python Decorators"  
author: "Ravi Vishwakarma"  
published: 2025-09-25  
updated: 2025-09-25  
canonical: https://www.mindstick.com/interview/34380/explain-the-python-decorators  
category: "python"  
tags: ["python-3.4", "Python 3"]  
reading_time: 4 minutes  

---

# Explain the Python Decorators

> A [**decorator in Python**](https://www.mindstick.com/interview/34360/what-are-python-decorators) is a **function that takes another function as input, adds some extra behavior, and returns a new function** — without changing the original function’s code.

It’s often used for **logging, authentication, caching, timing, etc.**

## How Functions Work in Python

In Python, **functions are first-class objects** — meaning you can:

- Assign them to variables
- Pass them as arguments
- Return them from other functions
- That’s why decorators are possible.

## Basic Example (function inside function)

```python
def outer_function(func):
    def inner_function():
        print("Before the function runs")
        func()
        print("After the function runs")
    return inner_function

def say_hello():
    print("Hello!")

# Wrap manually
decorated = outer_function(say_hello)
decorated()
```

## Output:

```plaintext
Before the function runs
Hello!
After the function runs
```

## Using `@decorator` Syntax

Python provides a shorthand with `@`:

```python
def outer_function(func):
    def inner_function():
        print("Before")
        func()
        print("After")
    return inner_function

@outer_function   # same as: say_hi = outer_function(say_hi)
def say_hi():
    print("Hi there!")

say_hi()
```

## Output:

```plaintext
Before
Hi there!
After
```

## Decorator with Arguments

```python
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function")
        result = func(*args, **kwargs)
        print("After function")
        return result
    return wrapper

@my_decorator
def add(a, b):
    return a + b

print(add(5, 3))
```

## Output:

```plaintext
Before function
After function
8
```

## Real-World Examples

### 1. Logging

```python
def log(func):
    def wrapper(*args, **kwargs):
        print(f"Running {func.__name__} with {args}, {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@log
def multiply(a, b):
    return a * b

print(multiply(4, 5))
```

### 2. Authentication Example

```python
def require_admin(func):
    def wrapper(user, *args, **kwargs):
        if user != "admin":
            print("Access denied!")
            return
        return func(user, *args, **kwargs)
    return wrapper

@require_admin
def delete_user(user, target):
    print(f"{user} deleted {target}")

delete_user("guest", "Bob")   # denied
delete_user("admin", "Bob")   # allowed
```

## Decorators for Classes

Python has built-in decorators too:

- `@staticmethod`
- `@classmethod`
- `@property`

Example:

```python
class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name.upper()

p = Person("alice")
print(p.name)  # ALICE
```

- A **decorator** is just a function that wraps another function.
- Use `@decorator_name` above a function to apply it.
- Very handy for cross-cutting concerns (logging, security, retry logic, etc.).

## Answers

### Answer by Ravi Vishwakarma

> A [**decorator in Python**](https://www.mindstick.com/interview/34360/what-are-python-decorators) is a **function that takes another function as input, adds some extra behavior, and returns a new function** — without changing the original function’s code.

It’s often used for **logging, authentication, caching, timing, etc.**

## How Functions Work in Python

In Python, **functions are first-class objects** — meaning you can:

- Assign them to variables
- Pass them as arguments
- Return them from other functions
- That’s why decorators are possible.

## Basic Example (function inside function)

```python
def outer_function(func):
    def inner_function():
        print("Before the function runs")
        func()
        print("After the function runs")
    return inner_function

def say_hello():
    print("Hello!")

# Wrap manually
decorated = outer_function(say_hello)
decorated()
```

## Output:

```plaintext
Before the function runs
Hello!
After the function runs
```

## Using `@decorator` Syntax

Python provides a shorthand with `@`:

```python
def outer_function(func):
    def inner_function():
        print("Before")
        func()
        print("After")
    return inner_function

@outer_function   # same as: say_hi = outer_function(say_hi)
def say_hi():
    print("Hi there!")

say_hi()
```

## Output:

```plaintext
Before
Hi there!
After
```

## Decorator with Arguments

```python
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before function")
        result = func(*args, **kwargs)
        print("After function")
        return result
    return wrapper

@my_decorator
def add(a, b):
    return a + b

print(add(5, 3))
```

## Output:

```plaintext
Before function
After function
8
```

## Real-World Examples

### 1. Logging

```python
def log(func):
    def wrapper(*args, **kwargs):
        print(f"Running {func.__name__} with {args}, {kwargs}")
        return func(*args, **kwargs)
    return wrapper

@log
def multiply(a, b):
    return a * b

print(multiply(4, 5))
```

### 2. Authentication Example

```python
def require_admin(func):
    def wrapper(user, *args, **kwargs):
        if user != "admin":
            print("Access denied!")
            return
        return func(user, *args, **kwargs)
    return wrapper

@require_admin
def delete_user(user, target):
    print(f"{user} deleted {target}")

delete_user("guest", "Bob")   # denied
delete_user("admin", "Bob")   # allowed
```

## Decorators for Classes

Python has built-in decorators too:

- `@staticmethod`
- `@classmethod`
- `@property`

Example:

```python
class Person:
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name.upper()

p = Person("alice")
print(p.name)  # ALICE
```

- A **decorator** is just a function that wraps another function.
- Use `@decorator_name` above a function to apply it.
- Very handy for cross-cutting concerns (logging, security, retry logic, etc.).


---

Original Source: https://www.mindstick.com/interview/34380/explain-the-python-decorators

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
