1

私はクラスウィンドウを持っています。このクラスには、そのウィンドウでクリックされたコントロールのIDを引数に取得するメソッドonClickがあります(動作方法を変更することはできません):

 class Window(SoneBaseWindowClass):

    def onClick(self,controlID):
        print controlID

メソッドをコールバック スタックに追加するデコレータを作成したいと考えています。また、特定のコントロールがクリックされると、メソッド onClick が特定のメソッドを呼び出します。そう:

class Window(SoneBaseWindowClass):
    def __init__(self):
        callback_stack = {}

    def onClick(self,controlId):
        callback = self.callback_stack.get(controlID)
        if callback is not None:
            callback()

    # suppose to add decorated method to a callback_stack
    def onclick_decorator(method):
        pass

そのため、にメソッドを追加するデコレータを作成する必要がありcallback_stackます。使用例。

class MyWindow(Window):

    @onclick_decorator(12345)
    def someMethod(self):
        print "Gets called when control with id 12345 clicked"

onclick_decorator 実際問題は、そのメソッドに渡されない Selfからクラスへのアクセスを取得するにはどうすればよいかということです。したがって、クラスにアクセスできると想定できますが、その方法を理解できませんでした。

4

1 に答える 1

2

The way to deal with this kind of situation is to have the decorator to add the decorated methods to a data structure (CallbackStack in your case) - but to attach that data structure to the class, you need some action when the class is created (i.e. parsed) - since while it is being parsed, the decorator, as you say, don't have access to either the instance or class.

In modern Python (even Python 2) there are two ways to do that: you eitehr use a metclass, or a class decorator. But I don think class decorators are available for Python 2.4 - so you will need to have a metaclass.

It is not that complicated - the __new__method on the metaclass gets passd the dictionary that was constructed during parsing. All your decorator has to do is to mark the desired methods with an attribute that the metaclass can find - and build your callback_stack from these markings. The call_back stack can even be a dictionary:

def on_click_decorator(key):
    def real_decorator(func):
        setattr(func, "_callback_to", key)
        return func
    return real_decorator


class Meta(type):
    def __new__(metacls, name, bases, dct):
        callback_stack = {}
        for name, value in dct.items():
            if hasattr(value, "_callback_to"):
                callback_stack[value._callback_to] = key
        dct["callback_stack"] = callback_stack
        # we've done all needed manipulation - no
        # need for the class to be from a special type - so we
        # don't call type.__new__
        return type(name, bases, dct)

Now you can, from inside your methods, call self.callback_stack[controlID] to retrieve the registered functions (ou get them as functions not methods with the code above, so pass "self" explicitly to them).

于 2012-04-13T16:08:03.440 に答える