2016-03-13 2 views
0

У меня есть функция декоратора my_fun(I,k) и применяется к функции add(x,y) как таковойPython декоратор доступа к переменным

@my_fun(4,5) 
def add(x,y): return x+y 

Я новичок в Python хотел бы знать, если я пишу my_fun функцию

  1. Как я могу получить x,y в методе добавления в my_fun?
  2. Как я могу получить доступ к возвращаемому значению add в функции декоратора?

Я немного смущен синтаксисом и понятиями любое объяснение поможет.

ответ

2

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

# Takes the arguments for the decorator and makes them accessible inside 
def my_fun(decorator_argument1, decorator_argument2): 

    # Takes the function so that it can be wrapped. 
    def wrapfunc(func): 

     # Here we are actually going to wrap the function ... finally 
     def wrapper(*args, **kwargs): 

      # Call the function with the args and kwargs 
      res = func(*args, **kwargs) 

      # return this result 
      return res 

     # Replace the decorated function with the wrapper 
     return wrapper 
    # Return the wrapper for the function wrapper :-) 
    return wrapfunc 

В вашем случае, если вы хотите использовать только декоратору с функцией вам не нужно возиться с *args, **kwargs и заменить его:

  def wrapper(x, y): 

      # Here you can do stuff with x and y, i.e. print(x) 

      # Call the function with x and y 
      res = func(x, y) 

      # Here you can do stuff with the result, i.e. res = res * decorator_argument1 

      return res 

Я указал место, где вы можете получить доступ к x и y и результату.

Если вы хотите предопределять значения для x и y, пользовательский декоратор не лучший способ. Вы можете использовать по умолчанию:

def add(x=4,y=5): return x+y 

add() # returns 9 
add(2) # returns 7 
add(5, 10) # returns 15 

или если вы хотите, чтобы исправить аргумент, вы должны использовать functools.partial

+4

Если вы хотите, чтобы декоратор принимал такие параметры, как '4,5' в коде OP, тогда должен быть дополнительный уровень обертывания , – interjay

+0

Да, как добавить дополнительную оболочку для аргументов, а также –

+0

отредактировал ответ для необязательных аргументов. Я думал, что в основном это касается доступа к «х» и «у» и результата вызова функции, и другой слой будет немного запутывающим. Сожалею. – MSeifert

0

Если вы передаете аргументы декоратора с @my_fun(4, 5), вам нужны три уровня вложенности функций для реализации декоратор самым простым способом. Внешний уровень - «фабрика декораторов». Он возвращает функцию среднего уровня, декоратор. Декоратор получает вызов с функцией, которую он украшает как аргумент, и ему нужно вернуть внутреннюю самую вложенную функцию - оболочку. Функция-оболочка - это тот, который вызывается пользователем.

def decorator_factory(deco_arg, deco_arg2): # name this whatever you want to use with @syntax 
    def decorator(func): 
     def wrapper(func_arg, func_arg2): 
      # This is a closure! 
      # In here you can write code using the arguments from the enclosing scpoes. e.g.: 
      return func(func_arg*deco_arg, func_arg2*deco_arg2) # uses args from all levels 
     return wrapper 
    return decorator 

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

(Обратите внимание, что если вы хотите, чтобы ваш декоратор, чтобы иметь возможность украсить множество различных функций, вы можете функция wrapper принять *args и **kwargs и передавать их func. Приведенный выше пример работает только для функций, которые принимают ровно два аргументы. Такое ограничение может быть совершенно разумным для некоторых целей, но не всегда.)

Смежные вопросы