2

私は次のコードを持っています。ほとんどのコードはぎこちなく、紛らわしく、状況に応じて見えるように見えますが、そのほとんどは、私が問題を抱えているはるかに大きなコードの部分を示すためのものです。注意深く読んでください

# The following part is just to demonstrate the behavior AND CANNOT BE CHANGED UNDER NO CIRCUMSTANCES
# Just define something so you can access something like derived.obj.foo(x)
class Basic(object):
    def foo(self, x=10):
        return x*x

class Derived(object):
    def info(self, x):
        return "Info of Derived: "+str(x) 
    def set(self, obj):
        self.obj = obj

# The following piece of code might be changed, but I would rather not
class DeviceProxy(object):
    def __init__(self):
        # just to set up something that somewhat behaves as the real code in question
        self.proxy = Derived()
        self.proxy.set(Basic())

    # crucial part: I want any attributes forwarded to the proxy object here, without knowing beforehand what the names will be
    def __getattr__(self, attr):
        return getattr(self.proxy, attr)

# ======================================
# This code is the only I want to change to get things work

# Original __getattr__ function
original = DeviceProxy.__getattr__

# wrapper for the __getattr__ function to log/print out any attribute/parameter/argument/...
def mygetattr(device, key):
    attr = original(device, key) 
    if callable(attr):
        def wrapper(*args, **kw):
            print('%r called with %r and %r' % (attr, args, kw))
            return attr(*args, **kw)
        return wrapper
    else:  
        print "not callable: ", attr
        return attr

DeviceProxy.__getattr__ = mygetattr


# make an instance of the DeviceProxy class and call the double-dotted function
dev = DeviceProxy()
print dev.info(1)
print dev.obj.foo(3) 

私が望むのは、すべてのメソッド呼び出しをキャッチして、DeviceProxyすべての引数/パラメーターなどを出力できるようにすることです。与えられた例では、これは を呼び出すときにうまく機能しinfo(1)、すべての情報が出力されます。しかし、二重点の関数を呼び出すと、dev.obj.foo(3)これは呼び出し可能ではないというメッセージしか表示されません。

上記のコードを変更して、2 番目のケースでも情報を取得するにはどうすればよいですか? 以下のコードのみ===変更できます。

4

1 に答える 1

3

__getattr__onだけがあり、devthis 内から、するときに__getattr__アクセスできるようにします。これは不可能です。属性アクセスは、全体としてアクセスされる「ドット関数」ではありません。属性アクセス (ドット) のシーケンスは、左から右に一度に 1 つずつ評価されます。にアクセスする時点では、後でアクセスするかどうかを知る方法はありません。このメソッドは、後でアクセスする可能性のある結果の属性ではなく、 でアクセスしている属性のみを認識します。foodev.obj.foodev.objfoodev.__getattr__dev

あなたが望むものを達成する唯一の方法は、いくつかのラッピング動作も に含めることですobj。「ベース」/「派生」クラスを変更できないと言うので、そのようにすることはできません。理論的にDeviceProxy.__getattr__は、アクセスした属性の実際の値を返すのではなく、そのオブジェクトを別のプロキシでラップしてプロキシを返すことができます。ただし、シン プロキシに大量のオブジェクトがラップされる可能性があるため、コードの理解とデバッグが難しくなる可能性があります。

于 2012-12-08T19:10:00.577 に答える