4

__getattribute__パラメータが 2 つしかないようです(self, name)

ただし、実際のコードでは、インターセプトしているメソッドが実際に引数を取ります。

これらの引数にアクセスする方法はありますか?

ありがとう、

チャーリー

4

7 に答える 7

6

__getattribute__は単に要求された属性を返します。メソッドの場合は、 __ call__インターフェイスを使用してそれを呼び出します。

メソッドを返す代わりに、次のようにラッパーを返します。

def __getattribute__(self, attr):
     def make_interceptor(callble):
         def func(*args, **kwargs):
             print args, kwargs
             return callble(*args, **kwargs)
         return func
     att = self.__dict__[attr]
     if callable(att):
        return make_interceptor(att)
于 2009-05-26T18:06:57.940 に答える
3

Python でのメソッド呼び出しは 2 段階のプロセスです。最初に関数が検索され、次に呼び出されます。より複雑な議論については、この質問に対する私の回答を参照してください。

したがって、次のようなことをする必要があります。

def __getattribute__(self, key):
    if key == "something_interesting":
        def func(*args, **kwargs):
            # use arguments, and possibly the self variable from outer scope
        return func
    else:
        return object.__getattribute__(self, key)

また、 __getattribute__ をオーバーライドすることは、通常は悪い考えです。これはすべての属性アクセスで呼び出されるため、非常に簡単に無限ループに陥り、すべてを正しく行ったとしても、パフォーマンスに大きな影響を与えます。あなたの目的には __getattr__ では不十分だと確信していますか? または、関数を返す記述子オブジェクトでさえあるかもしれません。記述子は通常、再利用がはるかに優れています。

于 2009-05-26T18:06:50.840 に答える
1

これは、要求された関数の代わりに呼び出し可能な「ラッパー」インスタンスを返す Unknown の提案のバリエーションです。これには、メソッドを装飾する必要はありません。

class F(object):
   def __init__(self, func):
      self.func = func
      return
   def __call__(self, *args, **kw):
      print "Calling %r:" % self.func
      print "  args: %r" % (args,)
      print "  kw: %r" % kw
      return self.func(*args,**kw)

class C(object):
   def __init__(self):
      self.a = 'an attribute that is not callable.'
      return
   def __getattribute__(self,name):
      attr = object.__getattribute__(self,name)
      if callable(attr):
         # Return a callable object that can examine, and even
         # modify the arguments prior to calling the method.
         return F(attr)
      # Return the reference to any non-callable attribute.
      return attr
   def m(self, *a, **kw):
      print "hello from m!"
      return

>>> c=C()
>>> c.a
'an attribute that is not callable.'
>>> c.m
<__main__.F object at 0x63ff30>
>>> c.m(1,2,y=25,z=26)
Calling <bound method C.m of <__main__.C object at 0x63fe90>>:
  args: (1, 2)
  kw: {'y': 25, 'z': 26}
hello from m!
>>> 

上記の Ants Aasmaは、 を使用する場合の再帰に関して重要な点を指摘して__getattribute__います。メソッド内のものも含め、のすべての属性ルックアップによって呼び出されます。他の例のいくつかには、最大スタック深度を超えるまで再帰する内部への参照が含まれています! これを回避するには、基本クラスのバージョンのいずれかを使用します(例: .)self__getattribute__self.__dict____getattribute____getattribute__object.__getattribute__(self,name)

于 2009-12-10T11:08:25.400 に答える
1

私はあなたができるとは思わない。__getattribute__メソッド呼び出しをインターセプトせず、メソッド名のルックアップのみをインターセプトします。したがって、関数 (または呼び出し可能なオブジェクト) を返す必要があります。これは、呼び出しサイトで指定されたパラメーターで呼び出されます。

特に、 を受け取る関数を返す場合(*args, **kwargs)、その関数内で必要に応じて引数を調べることができます。

おもう。私は Python の専門家ではありません。

于 2009-05-26T18:08:57.967 に答える
1

正直なところ、あなたの質問を理解しているかどうかわかりません。getattribute をオーバーライドして元の属性を保持する方法が必要な場合は、使用できます__dict__

def __getattribute__(self, attr):
    if attr in self.__dict__:
          return self.__dict__[attr]
    # Add your changes here
于 2009-05-26T17:58:47.643 に答える
0

はい

def argumentViewer(func):
    def newfunc(*args, **kwargs):
        print "Calling %r with %r %r" % (func, args, kwargs)
        return func(*args, **kwargs)
    return newfunc

class Foo(object):
    def __getattribute__(self, name):
        print "retrieving data"
        return object.__getattribute__(self, name)

    @argumentViewer
    def bar(self, a, b):
        return a+b

# Output
>>> a=Foo()
>>> a.bar
retrieving data
<bound method Foo.newfunc of <__main__.Foo object at 0x01B0E3D0>>
>>> a.bar(2,5)
retrieving data
Calling <function bar at 0x01B0ACF0> with (<__main__.Foo object at 0x01B0E3D0>, 2, 5) {}
7
于 2009-05-26T18:45:48.360 に答える