Не набиваюсь в знатоки Python, просто скажу как я понял их:
Допустим, у нас есть некоторая функция, которая отправляет файл по почте
def send_mail(text):
pass
И вдруг, нам захотелось, что бы отправка логировалась как то по особому, причем функцию логирования мы хотим подключить и к другим нашим функциям, которых так много, что везде писать одно и то же не с руки (т.е. не только при отправке писем, но и при сохранении на диск непример). Для этого мы пишем функцию, куда декоратор @ автоматически подставит нашу функцию. Возвращать же наша функция тоже должна функцию.
def my_loger(func): # Объявляем декоратор
def new_func(*args, **kwarts): # Объявляем функцию, которая заменит исходную
print("Begin send") # делаем что то важное
func(*args, **kwargs) # Вызываем исходную функцию
print("End send") # Опять делаем что то важное
return new_func # Возвращаем новую функцию
Теперь, при объявлении функций мы можем перед ней написать @my_loger, и логирование будет подключено автоматически.
т.е., написав следующее
@my_loger
def send_mail(test):
pass
фактически мы получим код
def send_mail(text)
print("Begin send")
# Some actions
print("End send")