2

デコレータが呼び出されたとき、 mymethod はまだメソッドではないようです。

import inspect

class decorator(object):
    def __call__(self, call):
        if inspect.ismethod(call): #Not working yet
            obj = "method"
            args = inspect.getargspec(call)[0][1:]
        elif inspect.isfunction(call):
            obj = "function"
            args = inspect.getargspec(call)[0]
        elif inspect.isclass(call):
            obj = "class"
            args = inspect.getargspec(call.__init__)[0][1:]

        args="(%s)" % repr(args)[1:-1].replace("'","")
        print "Decorate %s %s%s" % (obj, call.__name__, args)
        return call


@decorator()
def myfunction (a,b): pass

@decorator()
class myclass():
    def __init__(self, a, b): pass

    @decorator()
    def mymethod(self, a, b): pass

if inspect.isfunction(myclass.mymethod):
    print "mymethod is a function"
if inspect.ismethod(myclass.mymethod):
    print "mymethod is a method"

出力:

Decorate function myfunction(a, b)
Decorate function mymethod(self, a, b)
Decorate class myclass(a, b)
mymethod is a method

最初の引数が「自己」であるかどうかはわかりますが、汚れの少ない解決策はありますか?

編集:なぜですか?

それが関数またはクラスである場合、呼び出し可能オブジェクトとその引数のリストを作成したいのですが、予想される引数を渡すことができます。それから呼び出しますが、メソッドの場合は、渡す「自己」引数がありません. 何かのようなもの:

import inspect

class ToDo(object):
    calls=[]

    def do(self, **kwargs):
        for call in self.calls:
            if 'self' in call.args:
                print "This will fail."
            args = {}
            for arg in call.args:
                args[arg]=kwargs.get(arg, None)
            call.call(**args)

TODO = ToDo()

class decorator(object):
    def __call__(self, call):
        if inspect.isfunction(call):
            args = inspect.getargspec(call)[0]
        elif inspect.isclass(call):
            args = inspect.getargspec(call.__init__)[0][1:]

        self.call = call
        self.args = args
        TODO.calls.append(self)
        return call

TODO.do(a=1, b=2)
4

2 に答える 2

1

あなたは本当にその区別をすることはできません。次に例を示します。

>>> class A(object):
...    pass
...
>>> def foo(x): return 3
...
>>> A.foo = foo
>>> type(foo)
<type 'function'>
>>> type(A.foo)
<type 'instancemethod'>

ご覧のとおり、関数であるため、デコレータを に適用できますfoo。ただし、その関数を参照するクラス属性を作成するだけで、装飾されたメソッドを作成できます。

(この例は Python 2.7 のものです。上記の動作を変更するために Python 3 で何かが変更されたかどうかはわかりません。)

于 2013-05-18T14:03:14.917 に答える