1. ホーム
  2. python

[解決済み] クラスの飾りつけはどうする?

2022-03-03 18:29:20

質問

Python 2.5では、クラスを装飾するデコレータを作成する方法はありますか? 具体的には、デコレータを使ってクラスにメンバーを追加し、コンストラクタがそのメンバーの値を取るように変更したいのです。

以下のようなものを探しています('class Foo:'でシンタックスエラーが発生します。

def getId(self): return self.__id

class addID(original_class):
    def __init__(self, id, *args, **kws):
        self.__id = id
        self.getId = getId
        original_class.__init__(self, *args, **kws)

@addID
class Foo:
    def __init__(self, value1):
        self.value1 = value1

if __name__ == '__main__':
    foo1 = Foo(5,1)
    print foo1.value1, foo1.getId()
    foo2 = Foo(15,2)
    print foo2.value1, foo2.getId()

私が本当に求めているのは、PythonでC#のインターフェイスのようなものを実現する方法なんでしょうね。私はパラダイムを切り替える必要があると思います。

どのように解決するのか?

私は、あなたが概説したアプローチの代わりに、サブクラスを検討することをお勧めします。しかし、あなたの具体的なシナリオを知らないので、YMMV :-)。

あなたが考えているのは、メタクラスです。その __new__ 関数にはクラスの定義案が渡され、クラスが作成される前にその定義を書き換えることができます。その際、コンストラクタをサブアウトして新しいコンストラクタを作ることができます。

def substitute_init(self, id, *args, **kwargs):
    pass

class FooMeta(type):

    def __new__(cls, name, bases, attrs):
        attrs['__init__'] = substitute_init
        return super(FooMeta, cls).__new__(cls, name, bases, attrs)

class Foo(object):

    __metaclass__ = FooMeta

    def __init__(self, value1):
        pass

コンストラクタを置き換えるというのは少し大げさかもしれませんが、この言語はこのような深いイントロスペクションや動的な修正をサポートする機能を備えています。