1

ディスクリプタとデコレータを交互に使用していることをお許しください。ここでそれらのいくつかが間違っている可能性があります。

メソッドについて何かを宣言的に指定するクラスを (たくさん) 書きたいと思います。

class Foo:

    @method_metadata(0,1,2)
    def some_method(self,input):
        print("I received some input: "+input)

その意図は、メソッドの動作を変更することではなく、(0,1,2) がこのメソッドに関連付けられていることを登録することだけです。

これを実現するために、次の記述子を作成しました。必要な 3 つのうち 2 つを提供してくれます。

class method_metadata:

    # 1 - I need to gather three things here: the parameters passed into the method descriptor (0,1,2) in my case
    # 2 - A reference to the method so I can call it later
    # 3 - The class that the method lives in - this is the one I can't figure out

    def __init__(self,*collection_args):

        # Achieved #1 here
        self.collection_args = collection_args

    def __call__(self,decorated_function):

        #Achieved #2 here:
        self.decorated_method = decorated_method

        #I'm not sure how to achieve #3 here.

        # inspect.getmembers(decorated_function) showed some promise, not sure if I should pursue that.

        # Alternatively, if I put a descriptor on the class that contains the method, I can iterate through the attributes and get what I need.  That'll be my fall-back solution but in my case it causes a bit of a problem because some attributes aren't happy to be read yet (they throw assertions because they're not initialized, etc).

        return decorated_function

問題のメソッドが Foo クラスに属していることを method_metadata 内で把握する方法はありますか?

PS - 私は Python 3.2 を使用しており、下位互換性は必要ありません。

4

1 に答える 1

0

クラスメンバー(関数またはクラスデータメンバー)が定義された時点では、それはそれを囲むクラスを認識していません。Pythonでキーワードが機能する方法は、ステートメントclassの本体内の式が評価され、にパックされてから、メタクラス(デフォルトでは)として渡されることです。それらが評価された時点(デコレータの適用を含む)では、最終的に追加されるクラスを参照する方法はありません。classdicttypemetaclass(classname, bases, members)

囲んでいるクラスについて知る必要のあるメタデータを「処理する」方法は、メタクラスまたはクラスデコレータを使用することです。また:

class Foo(metaclass=supporting_metaclass):

また

@supporting_class_decorator
class Foo:

効果にそれほど大きな違いはありません。クラスデコレータには、自分で作成するのではなく、完全に指定されたクラスから開始するという利点があるため、記述が簡単になる傾向があります。また、クラスデコレータをチェーン化することもできます。

いずれにせよ、メタ/デコレーションクラスの機械とメソッドデコレータの間にある程度の協力関係を構築する必要があります。できれば、どちらか一方を忘れないようにカナリアを配置する必要があります(たとえば、デコレートされたメソッドを非-メタ/クラスデコレータなしで呼び出し可能)。

于 2012-07-23T09:34:48.993 に答える