__getattr__ and functions that don't exist

Erik Johnson nobody
Thu May 25 20:15:46 EDT 2006


Thanks for your reply, Nick.  My first thought was "Ahhh, now I see. That's
slick!", but after playing with this a bit...

>>> class Foo:
...     def __getattr__(self, attr):
...         def intercepted(*args):
...             print "%s%s" % (attr, args)
...         return intercepted
...
>>> f = Foo()
>>> f
__repr__()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: __repr__ returned non-string (type NoneType)


    my thought is "Oooooh... that is some nasty voodoo there!"   Especially
if one wants to also preserve the basic functionality of __getattr__ so that
it still works to just get an attribute where no arguments were given.

    I was thinking it would be clean to maintain an interface where you
could call things like f.set_Spam('ham') and implement that as self.Spam =
'ham' without actually having to define all the set_XXX methods for all the
different things I would want to set on my object (as opposed to just making
an attribute assignment), but I am starting to think that is probably an
idea I should just simply abandon.

    I guess I don't quite follow the error above though. Can you explain
exactly what happens with just the evaluation of f?

Thanks,
-ej


"Nick Smallbone" <nick.smallbone at gmail.com> wrote in message
news:1148596303.833301.15190 at g10g2000cwb.googlegroups.com...
> Erik Johnson wrote:
> > Maybe I just don't know the right special function, but what I am
wanting to
> > do is write something akin to a __getattr__ function so that when you
try to
> > call an object method that doesn't exist, it get's intercepted *along
with
> > it's argument*, in the same manner as __getattr__ intercepts attributes
> > references for attributes that don't exist.
> >
> >
> > This doesn't quite work:
> >
> > >>> class Foo:
> > ...   def __getattr__(self, att_name, *args):
> > ...     print "%s%s" % (att_name, str(tuple(*args)))
> > ...
> > >>> f = Foo()
>
> The problem is that the call to f.bar happens in two stages: the
> interpreter calls getattr(f, "foo") to get a function, and then it
> calls that function. When __getattr__ is called, you can't tell what
> the parameters of the function call will be, or even if it'll be called
> at all - someone could have run "print f.bar".
>
> Instead, you can make __getattr__ return a function. Then *that*
> function will be called as f.bar, and you can print out its arguments
> there:
>
> class Foo:
>     def __getattr__(self, attr):
>         def intercepted(*args):
>             print "%s%s" % (attr, args)
>         return intercepted
>





More information about the Python-list mailing list