2

次のコードで説明するデコレータライブラリで、かなり奇妙な動作が発生しました。

from decorator import decorator    

@decorator
def wrap(f, a, *args, **kwargs):
    print 'Decorator:', a, args, kwargs
    return f(a, *args, **kwargs)

def mywrap(f):
    def new_f(a, *args, **kwargs):
        print 'Home made decorator:', a, args, kwargs
        return f(a, *args, **kwargs)
    return new_f

@wrap
def funcion(a, b, *args, **kwargs):
    pass

@mywrap
def myfuncion(a, b, *args, **kwargs):
    pass

funcion(1, b=2)
myfuncion(1, b=2)

このスクリプトを実行すると、次のように出力されます。

$ python /tmp/test.py 
Decorator: 1 (2,) {}
Home made decorator: 1 () {'b': 2}

'decorator'は、args内のkwargsを非表示にします。「自家製」のデコレータを使用せずに、これを解決するにはどうすればよいですか。

ありがとう。

4

1 に答える 1

5

で関数を呼び出したからといって、キーワード引数b=2は作成されません。元の関数の位置引数です。名前の付いた引数がなく、を指定した場合は、キーワード引数になります。bbbb=2 b

decoratorの動作は実際には最も正しいものです。生成されるラッパーは、と同じ署名を持ちますが、「自家製」デコレータによって作成されたラッパーは、名前付き引数としてfuncion()はありません。「自家製」ラッパーは、キーワードargではないことを明確にするの署名が呼び出し元から隠されているため、b「誤って」挿入bされます。kwargsmyfuncion()b

関数のシグネチャを保持することは、バグではなく機能ですdecorator

于 2011-07-14T22:08:41.163 に答える