Skip to content Skip to sidebar Skip to footer

Is There A Way To Access The Formal Parameters If You Implement __getattribute__

It seems as though __getattribute__ has only 2 parameters (self, name). However, in the actual code, the method I am intercepting actually takes arguments. Is there anyway to acces

Solution 1:

__getattribute__ simply returns the attribute that was requested, in case of a method, the __call__ interface is then used to call it.

Instead of returning the method, return a wrapper around it, for instance:

def__getattribute__(self, attr):
     defmake_interceptor(callble):
         deffunc(*args, **kwargs):
             print args, kwargs
             return callble(*args, **kwargs)
         return func
     att = self.__dict__[attr]
     ifcallable(att):
        return make_interceptor(att)

Solution 2:

Method invocation in Python is two step process, first a function is looked up, then it is invoked. For a more involved discussion see my answer to this question.

So you would need to do something like this:

def__getattribute__(self, key):
    if key == "something_interesting":
        deffunc(*args, **kwargs):
            # use arguments, and possibly the self variable from outer scopereturn func
    else:
        returnobject.__getattribute__(self, key)

Also, overriding __getattribute__ is usually a bad idea. Because it is called on all attribute accesses it is really easy to end up in an infinite loop, and even if you do everything correctly it ends up being a pretty big performance hit. Are you sure that __getattr__ won't be enough for your purposes? Or maybe even a descriptor object that returns functions. Descriptors are usually a lot better at reuse.

Solution 3:

Honestly I'm not sure I understand your question. If you want a way to override getattribute and yet keep the original attributes you can use __dict__

def__getattribute__(self, attr):
    if attr inself.__dict__:returnself.__dict__[attr]
    # Add your changes here

Solution 4:

I don't think you can. __getattribute__ doesn't intercept the method call, it only intercepts the method name lookup. So it should return a function (or callable object), which will then be called with whatever parameters specified at the call site.

In particular, if it returns a function which takes (*args, **kwargs), then in that function you can examine the arguments however you want.

I think. I'm not a Python expert.

Solution 5:

Here is a variation on Unknown's suggestion that returns a callable "wrapper" instance in place of the requested function. This does not require decorating any methods:

classF(object):
   def__init__(self, func):
      self.func = func
      returndef__call__(self, *args, **kw):
      print"Calling %r:" % self.func
      print"  args: %r" % (args,)
      print"  kw: %r" % kw
      return self.func(*args,**kw)

classC(object):
   def__init__(self):
      self.a = 'an attribute that is not callable.'returndef__getattribute__(self,name):
      attr = object.__getattribute__(self,name)
      ifcallable(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
   defm(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 above makes an important point regarding recursion when using __getattribute__. It is called by all attribute lookups on self, even those inside of the __getattribute__ method. Several of the other examples include references to self.__dict__ inside of __getattribute__ which will result in recursing until you exceed the maximum stack depth! To avoid this, use one of the base class' versions of __getattribute__ (e.g. object.__getattribute__(self,name).)

Post a Comment for "Is There A Way To Access The Formal Parameters If You Implement __getattribute__"