2013-03-14 3 views
2

У меня возник вопрос о работе декоратора. Я хотел бы объяснить мою проблему с помощью примераРабота декоратора

Код я реализовал понять декораторы

import sys 
import inspect 
def entryExit(f): 
    def new_f(self,*args, **kwargs): 
     print "Entering", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:] 
     f(self,*args)   
     print "Exited", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:]   
    return new_f 


class A: 
    @entryExit 
    def move(self,g,h): 
     print "hello"   
     print g,h    

    @entryExit  
    def move1(self,m,n): 
     print "hello"   
     print m,n 
     return m 
a=A() 
a.move(5,7) 
h=a.move1(3,4) 
print h 

Выходной сигнал этого кода

Entering move A ['g', 'h'] 
hello 
5 7 
Exited move A ['g', 'h'] 
Entering move1 A ['m', 'n'] 
hello 
3 4 
Exited move1 A ['m', 'n'] 
None 

Последняя строка выходных дисплеев None. Но фактический смысл метода изменяется с помощью декораторов. Оператор return в методе move1 не был выполнен. На самом деле выход я должен был бы быть

Entering move A ['g', 'h'] 
hello 
5 7 
Exited move A ['g', 'h'] 
Entering move1 A ['m', 'n'] 
hello 
3 4 
Exited move1 A ['m', 'n'] 
3 

Так я сделал какую-либо ошибку при создании декоратора или декораторы всегда игнорирует заявление возвращения в функции?

+0

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

ответ

4

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

Следующая:

def new_f(self,*args, **kwargs): 
    print "Entering", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:] 
    f(self,*args)   
    print "Exited", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:]   

следует читать:

def new_f(self,*args, **kwargs): 
    print "Entering", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:] 
    ret = f(self,*args)   
    print "Exited", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:]   
    return ret 

Ваш текущий код игнорирует возвращаемое значение f(self,*args) и неявно возвращает None.

+0

@ NPE Большое вам спасибо. Все это имеет смысл сейчас. У меня есть еще одно сомнение в том, что можно получить имя параметра, которое было возвращено во время выполнения. – Kaushik

+0

В моем случае это было бы. Можно ли получить с помощью декоратора? – Kaushik

+0

@karthik: Нет, это внутри источника функции. (Зачем вам это нужно?) –

5

Для того, чтобы функция возвращает значение, вы должны изменить определение декоратора быть:

def new_f(self,*args, **kwargs): 
    print "Entering", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:] 
    ret = f(self,*args)   
    print "Exited", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:]  
    return ret  
return new_f 

Это не то, что декораторы «всегда игнорируют» обратное заявление, но вы должны обращаться вернуть себя - так же, как вам нужно было использовать *args и **kwargs для обработки аргументов.

1

Попробуйте это:

def new_f(self,*args, **kwargs): 
     print "Entering", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:] 
     r = f(self,*args)   
     print "Exited", f.__name__,self.__class__.__name__,inspect.getargspec(f).args[1:] 
     return r  
return new_f 

Возвращение происходит, когда вы на самом деле вызов функции внутри декоратора. Таким образом, вы также должны вернуть его из украшенной функции.

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