2013-03-14 59 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的最后一道防线。但是通过使用装饰器来改变方法的实际含义。没有执行方法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

装饰者*只是功能*,所以你需要像对待任何其他链接函数调用.. – 2013-03-14 15:20:20

回答

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 2013-03-14 15:27:47

+0

在我的情况下,它会是'。是否有可能使用装饰器检索? – Kaushik 2013-03-14 15:28:39

+0

@karthik:不,这是函数的源头。 (为什么你需要它?) – 2013-03-14 15:29:27

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 

这并不是说装饰“始终忽略” return语句,但你必须处理返回自己 - 就像您必须使用*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 

返回发生在你实际调用内部装饰功能。所以,你也需要从装饰函数中返回它。