25

これは、デコレータに直面したときに最初に出会う例です。しかし、私は自分が何を望んでいるのかを正確に理解することができません。

LOGという名前のシンプルなデコレータ。これは次のように機能するはずです。

@LOG
def f(a, b=2, *c, **d):
    pass

結果は次のようになります。

f(1, pippo=4, paperino='luca')
===== Enter f =====
a = 1
b = 2
pippo = 4
paperino = luca
===== Exit f =====

関数にパラメーターとして渡されたすべての引数は、その値とともに表示されます。

主に、関数に引数を渡すことができるさまざまな方法があるため、問題が思ったよりも難しいことがわかりました(*cのタプルまたは**dの辞書について考えてみてください)。

私は解決策を試しましたが、それが正しいかどうかわかりません。これは次のように考えます。

def LOG(fn):
    import inspect
    varList, _, _, default = inspect.getargspec(fn)
    d = {}
    if default is not None:
        d = dict((varList[-len(default):][i], v) for i, v in enumerate(default))
    def f(*argt, **argd):
        print ('Enter %s' % fn).center(100, '=')
        d.update(dict((varList[i], v) for i, v in enumerate(argt)))
        d.update(argd)
        for c in d.iteritems():
            print '%s = %s' % c
        ret = fn(*argt, **argd)
        print 'return: %s' % ret
        print ('Exit %s' % fn).center(100, '=')
        return ret
    return f

思ったほど簡単ではないと思いますが、Googleで欲しいものが見つからなかったのは不思議です。

私の解決策が大丈夫かどうか教えてもらえますか?または、私が提案した問題のより良い解決策を提案できますか?

みなさん、ありがとうございました。

4

3 に答える 3

1

Everyhing is ok in your function. You seem to be lost with positional vs variable&keyword arguments.

Let me explain: positional arguments, a and b in your case, are obligatory (and may have default values). Other arguments are optional. If you want to make an argument obligatory or to have a default value, put it before *args and **kwargs. But remember that you can't supply an argument twice:

def x(a = 1, b = 2, *args, **kwargs):
    print a, b, args, kwargs

>>> x(3, 4, 5, b=6)
TypeError: x() got multiple values for keyword argument 'b'

There's another way, but not that readable, to have default values for arguments and have no positional args:

def x(*args, **kwargs):
    kwargs.updae({'a': 1, 'b': 2})

Your function that analyses the arguments is ok, though I don't understand why you write varargs and keywords into _. It passes arguments transparently:

def x(a = 1, b = 2, *args, **kwargs):
    print a, b, args, kwargs

def y(*args, **kwargs):
    x(*args, **kwargs)

>>> y(3, 4, 5, 6)
3 4 (5, 6) {}

>>> y(3, 4, 5, b=6)
TypeError: x() got multiple values for keyword argument 'b'
于 2009-10-30T11:33:34.733 に答える