2015-04-22 3 views
4

Я знаю, что есть подобный вопрос, но мой сценарий как-то иначе: смотрите коды:как использовать декоратор в классе

class MyClass(object): 
    def __init__(self, log_location) 
     self.logs = logging(log_location) # create log object by the log_location, this object should be used by the decorator fucntion 

    def record_log(log_object): 
     """ this is the decorator function 
     """ 
     def deco(func): 
      def wrap(*args, **kwargs): 
       rs = func() 

       # use log object to record log 
       if rs: 
        log_object.record('success') 
       else: 
        log_object.record('fail') 

      return wrap 
     return deco 

    @record_log(self.logs) 
    def test(self): 
     rs = do_some_thing 
     if rs: 
      return True 
     return False 

def main(): 
    my_class = MyClass() 
    my_class.test() 

Но, есть ошибка, как это:

@record_log(self.logs) 
NameError: name 'self' is not defined 

Должен ли я использовать атрибут instance self.logs в функции декоратора в таком сценарии, как это?

Большое спасибо!

+0

тогда, он скажет мне, что name'logs' не определено. – Spybdai

+0

то как мне передать self.logs? – Spybdai

+0

использование '@ decorator' отсутствует – Zaaferani

ответ

1

Есть несколько возражений о вашем коде:

  1. deco() является излишним. Вы можете напрямую вернуть wrap от record_log().

  2. Если вы только планируете украсить методы MyClass «s, то нет никакого смысла в переходе log_object к декоратору, а self.logs всегда будет использоваться. В противном случае рассмотрим возможность перемещения декоратора на уровень модуля, как это уже было предложено другими.

  3. Возвращаемое значение оформленного метода в настоящее время теряется.

  4. Призыв к украшенной функции не проходит self. Поэтому

Соответствующий код будет:

class MyClass(object): 
    def __init__(self, log_location): 
     self.logs = logging(log_location) 

    def record_log(func): 
     """ this is the decorator function 
     """ 
     def wrap(self): 
      rs = func(self) 
      # use log object to record log 
      if rs: 
       print 1 
       self.logs.record('success') 
      else: 
       print 2 
       self.logs.record('fail') 
      return rs 
     return wrap 

    @record_log 
    def test(self): 
     rs = do_some_thing 
     if rs: 
      return True 
     return False 
+1

Ницца ... но я думаю, вы должны использовать '* args, ** kwargs' в качестве параметров и получить' self' из 'args [0]', поэтому декоратор применим к другим методам класса. –

+0

Да, это правильно, спасибо! –

+0

Спасибо Вадиму за подробные комментарии о коде и благодарность за решение. Спасибо @tobias_k тоже очень много, но это решение лучше для моего сценария. спасибо всем ребятам за помощь !!! – Spybdai

1

Вы не можете передать ссылку на self или любой атрибут self на этом этапе. Линия @record_log выполнена (метод декорирован) до того, как код в main выполнен, то есть до того, как будет создан любой экземпляр MyClass - фактически, еще до того, как будет завершено определение MyClass! Но помните, что

@record_log(self.logs) 
def test(self, n): 

на самом деле просто синтаксический сахар для

test = record_log(self.logs)(test) 

Так один из способов работать вокруг проблемы можно было бы переопределить test в вашем __init__, т.е.

def __init__(self, log_location) 
    self.logs = logging(log_location) 
    self.test = record_log(self.logs)(self.test) 

Также обратите внимание на что ваш декоратор не передает никаких параметров до func и не возвращает результаты. Кроме того, он должен, вероятно, быть определен на уровне модуля (перед классом).

def record_log(log_object): 
    def deco(func): 
     def wrap(*args, **kwargs): 
      rs = func(*args, **kwargs) # pass parameters 
      if rs: 
       log_object.record('success') 
      else: 
       log_object.record('fail') 
      return rs # return result 
     return wrap 
    return deco 
+0

Hi tobias_k, спасибо за вашу помощь. Он работает сейчас, хотя и немного уродлив. И еще один вопрос: как @record_log (self.журналы) тест четкости (я, п): на самом деле просто синтаксический сахар для тест = record_log (self.logs) (тест) почему одна работа, в то время как другой не делает ??? – Spybdai

+0

@Spybdai Поскольку, как я уже сказал, оператор '@ record_log' выполняется _before_, класс даже полностью создан, а' self.test = ... 'выполняется, когда экземпляр класса создается. –

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