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ステートメントを「常に無視」するのではなく、引数を使用*argsして処理するのと同じ方法で、returnを自分で処理する必要があります。**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

これを試して:

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

デコレータ内で実際に関数を呼び出すと、戻りが発生します。したがって、decorated関数からも返す必要があります。

于 2013-03-14T15:20:31.730 に答える