1

プラネタリウム ソフトウェアの Python プラグインをコーディングしています。このプラグインには、プラネタリウム ソフトウェアの名前空間内のオブジェクトにアクセスするための関数が付属していますが、面倒で OOP ではありません。したがって、コーディングを合理化するために属性アクセスをオーバーロードするクラスを作成しようとしています。などのことができるようになりたいです。

rocket = RemoteObject('rocket')
rocket.color = blue

プラネタリウム ソフトウェアの名前空間のロケット オブジェクトの色を青に設定します。

でプロパティを定義する方法__init__は非常に近いです。私が抱えている問題の 1 つは、インスタンスの作成時にプロパティの名前を決定する必要があることです。もう 1 つの問題は、ディスクリプタ全般に対する私の理解不足によるものです。属性呼び出しは、getter と setter を呼び出すのではなく、プロパティ オブジェクト自体を返したり、上書きしたりしています。

これが私がこれまでに持っているものです:

class RemoteObject(object):
    def __init__(self,remote_object_name):
        self.normalattr = 'foo'
        self.normalmethod = lambda: 'spam'
        for attrname in get_remote_object_attrnames(remote_object_name):
            def _get(self):
                return fetch_remote_attr_value(remote_object_name,attrname)
            def _set(self,value):
                set_remote_attr_value(remote_object_name,attrname,value)
            setattr(self,attrname,property(_get,_set))

if __name__ == '__main__':
    get_remote_object_attrnames = lambda name: {'apple','banana','cherry'}
    fetch_remote_attr_value = lambda o,a: 'Reading %s.%s' % (o,a)
    set_remote_attr_value = lambda o,a,v: 'Writing %s.%s = %s' % (o,a,v)

    scene = RemoteObject('scene')
    for x in scene.__dict__.items(): print x
    print '-----'
    print scene.normalattr
    print scene.normalmethod()
    print scene.apple
    scene.banana = '42'
    print '-----'
    for x in scene.__dict__.items(): print x

実行すると、次のように返されます。

('cherry', <property object at 0x00CB65A0>)
('normalmethod', <function <lambda> at 0x00CB8FB0>)
('banana', <property object at 0x00CB65D0>)
('normalattr', 'foo')
('apple', <property object at 0x00CB6600>)
-----
foo
spam
<property object at 0x00CB6600>
-----
('cherry', <property object at 0x00CB65A0>)
('normalmethod', <function <lambda> at 0x00CB8FB0>)
('banana', '42')
('normalattr', 'foo')
('apple', <property object at 0x00CB6600>)

各インスタンスのプロパティを必要とする attrnames の動的セットを処理するより良い方法はありますか? プロパティ名に一致するインスタンス属性が、そのゲッターまたはセッターを実行するのではなく、プロパティ オブジェクト自体を返すのはなぜですか?

4

2 に答える 2

5

インスタンスにプロパティを定義することはできません。propertyオブジェクトは記述子であり、記述子__get____set__フックはクラスでのみサポートされています。

クラスでこれらすべてのプロパティを定義して無効AttributeErrorにする (おそらく無効なプロパティから をスローする) か、代わりに__getattr__andを使用する必要があり__setattr__ます。

「それらすべてを定義する」アプローチ:

class Foo(object):
    __enabled_properties = ()

    def __init__(self):
        self.__enabled_properties = ('bar',)

    @property
    def bar(self):
        if 'bar' not in self.__enabled_properties:
            raise AttributeError('bar')
        ...

    @bar.setter
    def bar(self, value):
        if 'bar' not in self.__enabled_properties:
            raise AttributeError('bar')
        ...

および__getattr__アプローチ__setattr__:

class Foo(object):
    __enabled_properties = ()
    __dynamic_properties = ('bar', 'spam', 'eggs')

    def __init__(self):
        self.__enabled_properties = ('bar',)

    def __getattr__(self, attr):
        if attr in self.__dynamic_properties:
            if attr not in self.__enabled_properties:
                raise AttributeError(attr)
            # Fetch a remote value here and return it
        if attr not in self.__dict__:
            raise AttributeError(attr)
        return self.__dict__[attr]

    def __setattr__(self, attr, value):
        if attr in self.__dynamic_properties:
            if attr not in self.__enabled_properties:
                raise AttributeError(attr)
            # Set a remote value here
        self.__dict__[attr] = value
于 2012-11-09T15:20:50.090 に答える
0

を使ったほうが楽かもしれませんnamedtuple。同様の答えを持つ別の質問があります:クラスにプロパティを動的に追加する方法は?

于 2012-11-09T15:23:25.757 に答える