Hi,

Using decorators can be very helpful but note that it can be very hard to debug the code with them. One of the issue that you can face is based on the decorators nature. Since decorator is simply a function that wraps original one so it will replace function.__name__ property to it’s own name and that can cause some misunderstanding during debugging your code and(or) using introspection(inspect/traceback module and etc. in some certain conditions). But Python already has the way how to deal with this case:

__author__ = 'artemr'

from functools import wraps


def without_wraps(func):
    def __wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return __wrapper

def with_wraps(func):
    @wraps(func)
    def __wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return __wrapper


@without_wraps
def my_func_a():
    """Here is my_func_a doc string text."""
    pass

@with_wraps
def my_func_b():
    """Here is my_func_b doc string text."""
    pass


# Below are the results without using @wraps decorator
print my_func_a.__doc__
>>> None
print my_func_a.__name__
>>> __wrapper

# Below are the results with using @wraps decorator
print my_func_b.__doc__
>>> Here is my_func_b doc string text.
print my_func_b.__name__
>>> my_func_b

Best Regards,
Artem