Декодер Python? - Может кто-нибудь объяснить это?

Извините, это очень широкий вопрос.

Код ниже - это фрагмент чего-то, найденного в Интернете. Ключевое, что меня интересует, это начало строки @protected - мне интересно, что это делает и как это делается? По-видимому, проверяется, что действительный пользователь зарегистрировался до выполнения функции do_upload_ajax. Это похоже на действительно эффективный способ аутентификации пользователей. Я не понимаю механику этой функции @, хотя - может ли кто-то направить меня в правильном направлении, чтобы объяснить, как это будет реализовано в реальном мире? Python 3 отвечает, пожалуйста. спасибо.

@bottle.route('/ajaxupload', method='POST')
@protected(check_valid_user) 
def do_upload_ajax():
    data = bottle.request.files.get('data')
    if data.file:
        size = 0

Ответ 1

Взгляните на этот огромный ответ/роман. Это одно из лучших объяснений, с которыми я столкнулся.

Самое короткое объяснение, которое я могу дать, это то, что декораторы завершают вашу функцию в другой функции, которая возвращает функцию.

Этот код, например:

@decorate
def foo(a):
  print a

будет эквивалентен этому коду, если вы удалите синтаксис декоратора:

def bar(a):
  print a

foo = decorate(bar)

Декораторы иногда берут параметры, которые передаются динамически сгенерированным функциям для изменения их вывода.

Другим термином, который вы должны прочитать, является закрытие, так как это концепция, которая позволяет декораторам работать.

Ответ 2

Декоратор - это функция, которая принимает функцию в качестве единственного параметра и возвращает функцию. Это полезно, чтобы "обернуть" функциональность одним и тем же кодом снова и снова.

Мы используем @func_name для указания декоратора, который будет применен к другой функции.

Следующий пример добавляет приветственное сообщение в строку, возвращаемую fun(). Принимает fun() в качестве параметра и возвращает welcome().

def decorate_message(fun):

    # Nested function
    def addWelcome(site_name):
        return "Welcome to " + fun(site_name)

    # Decorator returns a function
    return addWelcome

@decorate_message
def site(site_name):
    return site_name;

print site("Qaru")

Out[0]: "Welcome to Qaru"

Декораторы также могут быть полезны для присоединения данных (или добавления атрибута) к функциям.

Функция декоратора для прикрепления данных к функции

def attach_data(func):
       func.data = 3
       return func

@attach_data
def add (x, y):
       return x + y

print(add(2, 3))
# 5    
print(add.data)
# 3

Ответ 3

Синтаксис декоратора:

@protected(check_valid_user) 
def do_upload_ajax():
    "..."

эквивалентно

def do_upload_ajax():
    "..."
do_upload_ajax = protected(check_valid_user)(do_upload_ajax)

но без необходимости повторять одно и то же имя три раза. Нет ничего более.

Например, здесь возможна реализация protected():

import functools

def protected(check):
    def decorator(func): # it is called with a function to be decorated
        @functools.wraps(func) # preserve original name, docstring, etc
        def wrapper(*args, **kwargs):
            check(bottle.request) # raise an exception if the check fails
            return func(*args, **kwargs) # call the original function
        return wrapper # this will be assigned to the decorated name
    return decorator

Ответ 4

Декоратор - это функция, которая принимает другую функцию и расширяет поведение последней функции, не меняя ее явно. Python позволяет "вложенные" функции, т.е. (Функция внутри другой функции). Python также позволяет вам возвращать функции из других функций.

Скажем, ваша оригинальная функция называлась orig_func().

def orig_func():       #definition 
    print("Wheee!")

orig_func()            #calling 

Запустите этот файл, вызывается и печатает имя orig_func(). "Wheee".

Теперь, скажем, мы хотим изменить эту функцию, сделать что-то до этого вызова этой функции, а также что-то после этой функции.

Итак, мы можем сделать так: либо по опции 1, либо по опции 2

-------- вариант 1 ----------

def orig_func():
    print("Wheee!")

print "do something before"
orig_func()
print "do something after"

Обратите внимание, что мы не модифицировали orig_func. Вместо этого мы внесли изменения вне этой функции. Но может быть, мы хотим внести изменения таким образом, что при вызове orig_func мы можем сделать что-то до и после вызова функции. Итак, это то, что мы делаем.

-------- вариант 2 ----------

def orig_func():
    print "do something before"
    print("Whee!")
    print "do something after"

orig_func()

Мы достигли нашей цели. Но какой ценой? Нам пришлось изменить код orig_func. Это может быть не всегда возможно, особенно когда кто-то еще написал эту функцию. Тем не менее, мы хотим, чтобы при вызове этой функции она была изменена таким образом, что что-то до и/или после этого может быть выполнено. Затем декоратор помогает нам это сделать, не изменяя код orig_func. Мы создаем декоратор и можем сохранять то же имя, что и раньше. Итак, если наша функция вызывается, она прозрачно модифицируется. Мы проводим следующие шаги. а. Определите декоратор. В докораторе,  1) напишите код, чтобы сделать что-то перед orig_func, если хотите.  2) вызовите orig_func, чтобы выполнить свою работу.  3) напишите код, чтобы сделать что-то после orig_func, если хотите. б. Создайте декоратор с. Назовите декоратора.

Вот как мы это делаем.

=============================================== ==============

#-------- orig_func already given ----------
def orig_func():
   print("Wheee!")

#------ write decorator ------------
def my_decorator(some_function):
    def my_wrapper():
        print "do something before"   #do something before, if you want to
        some_function()
        print "do something after"    #do something after, if you want to
    return my_wrapper

#------ create decorator and call orig func --------
orig_func = my_decorator(orig_func)   #create decorator, modify functioning 
orig_func()                           #call modified orig_func

=============================================== ================

Обратите внимание, что теперь orig_func был изменен через декоратор. Итак, теперь, когда вы вызываете orig_func(), он будет запускать my_wrapper, который будет выполнять три шага, как уже описано.

Таким образом, вы изменили функционирование orig_func, не изменяя код orig_func, который является целью декоратора.

Ответ 5

Во-первых, нам нужно понять, зачем нам нужен Decorator.

Потребность в декораторе: Мы хотим использовать функцию уже встроенной библиотеки из Python, которая может выполнить нашу желаемую задачу.

Проблемы: Но проблема в том, что нам не нужен точный вывод функции. Мы хотим индивидуальный вывод. Хитрость в том, что мы не можем изменить исходный код функции. тут декоратор приходит к нам на помощь.

Решения: Декоратор принимает нашу необходимую функцию в качестве входных данных, оборачивает ее в функцию-обертку и делает 3 вещи:

  1. сделай что-нибудь раньше.
  2. затем вызовите нужную функцию().
  3. сделай что-нибудь после.

Общий код:

def my_decorator(desired_function):
    def my_wrapper():
        print "do something before"   #do something before, if you want to
        desired_function()
        print "do something after"    #do something after, if you want to
    return my_wrapper

desired_func = my_decorator(desired_func())   #create decorator
desired_func()                           #calling desired_func()   

Ответ 6

Поскольку некоторые люди любят учиться в видеоформате, вот лучшее объяснение, которое я наблюдал за декораторами Python. В этом видео (нажмите на ссылку, чтобы перейти к началу темы) Джеймс Пауэлл расскажет вам всю историю декораторов, и вы получите четкое представление о том, почему и как.

https://youtu.be/cKPlPJyQrt4?t=3099

Ответ 7

Декоратор - это просто функция, которая принимает другую функцию в качестве аргумента

Простой пример:

def get_function_name_dec(func):
  def wrapper(*arg):
      function_returns = func(*arg)  # What our function returns
      return func.__name__ + ": " + function_returns

  return wrapper

@get_function_name_dec
def hello_world():
    return "Hi"

print(hello_world())