Like __getattr__ but with args and kwargs as well

Chris Rebert clp2 at rebertia.com
Fri May 28 13:43:33 EDT 2010


On Fri, May 28, 2010 at 10:08 AM, Giampaolo Rodolà <g.rodola at gmail.com> wrote:
> I know, the title doesn't say much, but I had no better ideas. =)
> I have a class within a serie of redundant methods, which looks like this:
>
> class MixedAuthorizer:
>
>    def __init__(self, *args):
>        # expected a list of class instances
>        self.authorizers = args
>
>    def get_home(self, user):
>        for auth in self.authorizers:
>            if not auth.has_user(user):
>                continue
>            return auth.get_home(user)
>        return ""
>
>    def get_password(self, user):
>        for auth in self.authorizers:
>            if not auth.has_user(user):
>                continue
>            return auth.get_password(user)
>        return ""
>
>     # follows a long list of get_* methods as above
>     ...
>
>
> Considering that I always do the same thing (iterate over a list of
> objects -> call obj.has_user() -> call obj.get_*()) I would like to
> know if there's a more compact way to do that.
> What I basically need is something like __getattr__ but which provides
> the arguments and eventually the keyword arguments a method has been
> called with, other than just its name.
> Actually I'm not even sure whether Python can reach such a level of
> dynamism but I wanted to give it a try anyway.
> Is there a way to do such a thing?

There's no such "über-__getattr__", but with some indirection we can
achieve much the same effect:

#Note: Completely untested
from functools import partial

class Whatever(object):
    def _getter(self, _name, user, *args, **kwds):
        # I assume your actual code will use the *args and **kwds
        for auth in self.authorizers:
            if not auth.has_user(user):
                continue
            return getattr(auth, _name)(user)
        return ""

    def __getattr__(self, name):
        if name.startswith("get_"):
            return partial(self._getter, _name=name)
        else:
            raise AttributeError

Cheers,
Chris
--
http://blog.rebertia.com



More information about the Python-list mailing list