4

私はC++で書かれた大きなライブラリを持っていて、誰かがそれをpython(2.6)で自動的に使用するためのインターフェースを作成しました。今、私はgetterメソッドとsetterメソッドを持つクラスをたくさん持っています。本当に:私は彼らが嫌いです。

プロパティを使用して、よりPythonicなインターフェイスでクラスを再実装したいと思います。問題は、すべてのクラスに数百のゲッターとセッターがあり、私にはたくさんのクラスがあることです。プロパティを自動的に作成するにはどうすればよいですか?

たとえば、aおよび、、、などのメソッドで呼び出されるクラスがある場合MyClassGetX()プロパティSetX(x)(getterがある場合は読み取り可能、setterがある場合は書き込み可能)を使用して派生クラスを自動的に作成するにはどうすればよいですか。の上?手作業で作業する方がよい場合は、ゲッター/セッターのカップルをスキップすることを選択できるメカニズムが必要です。GetYSetYMyPythonicClassX

4

4 に答える 4

9

これがクラスデコレータでそれを行う方法です

def make_properties(c):
    from collections import defaultdict
    props=defaultdict(dict)
    for k,v in vars(c).items():
        if k.startswith("Get"):
            props[k[3:]]['getter']=v
        if k.startswith("Set"):
            props[k[3:]]['setter']=v
    for k,v in props.items():
        setattr(c,k,property(v.get('getter'),v.get('setter')))
    return c

@make_properties
class C(object):
    def GetX(self):
        print "GetX"
        return self._x

    def SetX(self, value):
        print "SetX"
        self._x = value

c=C()
c.X=5
c.X

これは、スキップするアイテムのリストを指定できる、もう少し複雑なバージョンです。

def make_properties(skip=None):
    if skip is None:
        skip=[]
    def f(c):
        from collections import defaultdict
        props=defaultdict(dict)
        for k,v in vars(c).items():
            if k.startswith("Get"):
                props[k[3:]]['getter']=v
            if k.startswith("Set"):
                props[k[3:]]['setter']=v
        for k,v in props.items():
            if k in skip:
                continue
            setattr(c,k,property(v.get('getter'),v.get('setter')))
        return c
    return f

@make_properties(skip=['Y'])
class C(object):
    def GetX(self):
        print "GetX"
        return self._x

    def SetX(self, value):
        print "SetX"
        self._x = value

    def GetY(self):
        print "GetY"
        return self._y

    def SetY(self, value):
        print "SetY"
        self._y = value

c=C()
c.X=5
c.X
c.Y=5
c.Y
于 2010-02-16T23:03:00.003 に答える
2

およびのようなすべての属性を検索し、クラスに適切なプロパティを追加するメタクラスを使用します。スキップされるプロパティを含むシーケンスに設定できるクラス属性があります。クラスでの属性の設定の詳細については、この回答を参照してください。Get*Set*

于 2010-02-16T22:30:25.533 に答える
1

魔法の使用には注意してください。特に、他の人のバインディングを魔法のように変更します。これには、次のような欠点があります。

  • あなたのコードは、同じライブラリにアクセスしている他の人と互換性がありません。誰かがモジュールの1つをインポートしたり、コードをコピーして貼り付けたりして、同じライブラリにアクセスするプログラムで完全に機能させることはできません。
  • お使いのインターフェイスは、C++コードへのインターフェイスとは異なります。これは、ラッパーがより優れた高レベルのインターフェースを提供する場合に意味がありますが、変更はごくわずかです。

使用しているライブラリを思いついたときに処理するだけでは意味がないかどうかを検討してください。

于 2010-02-16T23:42:14.823 に答える
1
class BaseObj:
    test = None
    def __init__(self, attributes_dict):
        self.attributes_dict = attributes_dict
        self.define_getters(attributes_dict.keys())
    def define_getters(self, attributes_names):
        for attribute_name in attributes_names:
            setattr(self, "get_"+attribute_name, self.getter_factory(attribute_name))
    def getter_factory(self, attribute_name):
        """Method for generating getter functions"""
        def getter():
            return self.attributes_dict[attribute_name]
        return getter

class DerivedObj(BaseObj):
    attributes_keys = ['name']
    def __init__(self, attributes_dict):
        BaseObj.__init__(self, attributes_dict)

a = DerivedObj({'name':'kuku'})
a.get_name()  # -> kuku
于 2013-10-07T15:26:13.860 に答える