1

基になる構造を動的に提示する必要がある IronPython でプロキシ オブジェクトを作成しようとしています。プロキシ自体に関数とプロパティを持たせる必要はありません。ランタイムですべての呼び出しをキャッチしようとしています。関数呼び出しをキャッチするのは簡単です。オブジェクトにgetattr () 関数を定義するだけでよく、下層のレイヤーに適切な関数が存在するかどうかをチェックし、関数のようなオブジェクトを返します。

プロパティに問題があります - 呼び出しコンテキストを区別する方法がわかりません。私のプロパティは左辺値または右辺値として呼び出されます:

o = myproxy.myproperty #基本的な.myproperty_get () を呼び出す必要があります

また

myproxy.myproperty = o #基本的な.myproperty_set (o) を呼び出す必要があります

Python の特殊関数のリストを見ましたが、適切なものが見つかりませんでした。

また、exec() と組み込みの property() 関数を組み合わせて、オンザフライでオブジェクトにプロパティを作成しようとしましたが、IronPython 1.1.2 には「新しい」モジュール全体が欠けていることがわかりました (これは IronPython 2.x に存在します)。ベータ版ですが、.NET 2.0 フレームワークのため、IP 1.x を使用します)。

何か案は?

4

2 に答える 2

2

これを試して:

class Test(object):
    _test = 0

    def test():
        def fget(self):
            return self._test
        def fset(self, value):
            self._test = value
        return locals()
    test = property(**test())

    def greet(self, name):
        print "hello", name


class Proxy(object):
    def __init__(self, obj):
        self._obj = obj

    def __getattribute__(self, key):
        obj = object.__getattribute__(self, "_obj")
        return getattr(obj, key)

    def __setattr__(self, name, value):
        if name == "_obj":
            object.__setattr__(self, name, value)
        else:
            obj = object.__getattribute__(self, "_obj")
            setattr(obj, name, value)


t = Test()
p = Proxy(t)
p.test = 1
assert t.test == p.test
p.greet("world")
于 2008-12-04T12:07:00.520 に答える
2

Pythonで必要なものの通常の実装は次のとおりです。

class CallProxy(object):
    'this class wraps a callable in an object'
    def __init__(self, fun):
        self.fun = fun

    def __call__(self, *args, **kwargs):
        return self.fun(*args, **kwargs)

class ObjProxy(object):
    ''' a proxy object intercepting attribute access
    '''
    def __init__(self, obj):
        self.__dict__['_ObjProxy__obj'] = obj

    def __getattr__(self, name):
        attr = getattr(self.__obj, name)
        if callable(attr):
            return CallProxy(attr)
        else:
            return attr

    def __setattr__(self, name, value):
        setattr(self.__obj, name, value)

これが期待どおりに動作することを証明するテストを作成しました。

#keep a list of calls to the TestObj for verification
call_log = list()
class TestObj(object):
    ''' test object on which to prove
        that the proxy implementation is correct
    '''
    def __init__(self):
        #example attribute
        self.a = 1
        self._c = 3

    def b(self):
        'example method'
        call_log.append('b')
        return 2

    def get_c(self):
        call_log.append('get_c')
        return self._c
    def set_c(self, value):
        call_log.append('set_c')
        self._c = value
    c = property(get_c, set_c, 'example property')

def verify(obj, a_val, b_val, c_val):
    'testing of the usual object semantics'
    assert obj.a == a_val
    obj.a = a_val + 1
    assert obj.a == a_val + 1
    assert obj.b() == b_val
    assert call_log[-1] == 'b'
    assert obj.c == c_val
    assert call_log[-1] == 'get_c'
    obj.c = c_val + 1
    assert call_log[-1] == 'set_c'
    assert obj.c == c_val + 1

def test():
    test = TestObj()
    proxy = ObjProxy(test)
    #check validity of the test
    verify(test, 1, 2, 3)
    #check proxy equivalent behavior
    verify(proxy, 2, 2, 4)
    #check that change is in the original object
    verify(test, 3, 2, 5)

if __name__ == '__main__':
    test()

これは、例外をスローするアサートなしで CPython で実行されます。IronPython は同等である必要があります。それ以外の場合は壊れており、このテストを単体テスト スイートに追加する必要があります。

于 2008-12-04T11:03:33.207 に答える