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

那么我在创建装饰器时是否犯了任何错误,或者装饰器总是忽略函数中的 return 语句?

4

3 回答 3

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 语句,而是你必须自己处理 return ——就像你必须使用*args**kwargs处理参数一样。

于 2013-03-14T15:19:21.270 回答
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

于 2013-03-14T15:19:52.387 回答
1

Try this:

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

The return happens when you actually call the function inside the decorator. So, you need to return it from the decorated function too.

于 2013-03-14T15:20:31.730 回答