# Python Decorators

Decorators allow you to modify the behavior of a function or class. They allow you to wrap another function in order to extend the behavior of the wrapped function, without permanently modifying it.

## Syntax

Decorators are usually called before the definition of a function you want to decorate.

```python
@my_decorator
def my_function():
    pass
```

## Creating a Decorator

A decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.

```python
def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
```

## Decorating Functions with Arguments

If the function being decorated takes arguments, the wrapper function needs to accept those arguments using `*args` and `**kwargs`.

```python
def do_twice(func):
    def wrapper_do_twice(*args, **kwargs):
        func(*args, **kwargs)
        func(*args, **kwargs)
    return wrapper_do_twice

@do_twice
def greet(name):
    print(f"Hello {name}")

greet("World")
```

[[programming/python/python]]