2015-08-23 6 views
1

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

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

Прямо сейчас он печатает на определении функции, а не на вызове функции. Смотрите этот пример кода:

def recursiveCounter(message): 
    def decorater(func): 
     def wrapper(count): 
      func(count) 
      if count < 10: 
       count += 1 
       wrapper(count) 

     print message 
     return wrapper 
    return decorater 


@recursiveCounter("hello I was called once") 
def counter(count): 
    print count 


counter(0) 

ответ

2

Ниже я добавил комментарии, чтобы указать, когда каждая линия работает:

def recursiveCounter(message): # when the decorator is defined 
    def decorater(func): # when the decorator is created - @recursiveCounter("hello I was called once") 
     def wrapper(count): # when the function is decorated - def counter(count): print count 
      func(count) # when the function is called - counter(0) 
      if count < 10: # when the function is called 
       count += 1 # when the function is called 
       wrapper(count) # when the function is called 

     print message # **when the function is decorated** 
     return wrapper # when the function is decorated 
    return decorater # when the decorator is created 

Как вы можете видеть, работает линия print message, когда функция получает оформленный, не тогда, когда он получает называется. Если вы хотите, чтобы он запускался при вызове функции, вы должны отложить его на один уровень дальше, поэтому он находится в пределах wrapper, а не decorater.


Если вы действительно хотите сохранить рекурсивную реализацию, переставить обертку для определения и вызова рекурсии:

... 
def wrapper(count): 
    def inner_wrapper(count): 
     if count < 10: 
      inner_wrapper(count + 1) 
    inner_wrapper(count) 
    print message 
+0

да, но когда он находится в обертке это будет называться в рекурсии. чего я не хочу. –

+0

@JohnSmith тогда не пишите рекурсивную обертку! Вы не можете иметь это в обоих направлениях. – jonrsharpe

+0

@JohnSmith или добавить 'inner_wrapper' для реализации рекурсии - см. Edit – jonrsharpe