我对装饰器的工作方式有疑问。我想用一个例子来解释我的问题
我为了解装饰器而实施的代码
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
中的return语句未执行。我需要的实际输出是
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语句?
答案 0 :(得分: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
来处理参数一样。 / p>
答案 1 :(得分: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
。
答案 2 :(得分: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
当您实际调用装饰器内的函数时,会发生返回。因此,您还需要从装饰函数返回它。