2

クラスの状態を変更するクラスメソッドデコレータを作成しようとしています。現在、実装に問題があります。

副次的な質問:デコレータはいつ呼び出されますか?クラスがインスタンス化されたときにロードされますか、それともクラスが読み取られた読み取り時にオンになりますか?

私がやろうとしていることはこれです:

class ObjMeta(object):
    methods = []

    # This should be a decorator that magically updates the 'methods'
    # attribute (or list) of this class that's being read by the proxying
    # class below.
    def method_wrapper(method):
        @functools.wraps(method)
        def wrapper(*args, **kwargs):
            ObjMeta.methods.append(method.__name__)
            return method(*args, **kwargs)
        return wrapper

    # Our methods
    @method_wrapper
    def method1(self, *args):
        return args

    @method_wrapper
    def method2(self, *args):
        return args


class Obj(object):

    klass = None

    def __init__(self, object_class=ObjMeta):
        self.klass = object_class
        self._set_methods(object_class)

    # We dynamically load the method proxies that calls to our meta class
    # that actually contains the methods. It's actually dependent to the 
    # meta class' methods attribute that contains a list of names of its
    # existing methods. This is where I wanted it to be done automagically with
    # the help of decorators
    def _set_methods(self, object_class):
        for method_name in object_class:
            setattr(self, method_name, self._proxy_method(method_name))

    # Proxies the method that's being called to our meta class
    def _proxy_method(self, method_name):
        def wrapper(*fargs, **fkwargs):
            return getattr(self.klass(*fargs, **fkwargs), method_name)
        return wrapper()

クラスでメソッドのリストを手動で書くのは醜いと思うので、おそらくデコレータがこれを修正するでしょう。

underscore.jsをpythonに移植するのは私が取り組んでいるオープンソースプロジェクト用です。itertoolsか何かを使うべきだと言っていることを理解しています。私はプログラミングと学習を愛するためだけにこれを行っています。ところで、プロジェクトはここでホストされています

ありがとう!

4

1 に答える 1

1

ここにはいくつか間違っていることがあります。

メソッド自体が呼び出されると、内部ラッパー内のすべてが呼び出されます。基本的に、メソッドを元の関数をラップする関数に置き換えます。したがって、現状のコードでは、呼び出されるたびにメソッド名がリストに追加されますが、これはおそらくあなたが望むものではありません。代わりに、その追加はmethod_wrapperレベル、つまり内部ラッパーの外側にある必要があります。これは、メソッドが定義されたときに呼び出されます。これは、クラスを含むモジュールが初めてインポートされたときに発生します。

2つ目の間違いは、実際にはメソッドを呼び出さないことです。単にメソッドを返すだけです。代わりにreturn method、指定されたargs-を使用してメソッドを呼び出す値を返す必要がありますreturn method(*args, **kwargs)

于 2012-07-03T09:54:04.347 に答える