Add "default" keyword to itemgetter and attrgetter.

1,272 views
Skip to first unread message

Miki Tebeka

unread,
Mar 22, 2012, 12:49:54 PM3/22/12
to python...@googlegroups.com
Repeating http://bugs.python.org/issue14384 ....

This way they will behave more like getattr and the dictionary get.

If default is not specified, then if the item/attr not found, an execption will be raised, which is the current behavior.

However if default is specified, then return it in case when item/attr not found - default value will be returned.

I wanted this when trying to get configuration from a list of objects. I'd like to do
    get = attrgetter('foo', None)
    return get(args) or get(config) or get(env)

In the case of multiple items/attrs then you return default in their place: attrgetter('x', 'y', default=7)(None) => (7, 7) In case of dotted attribute again it'll return default value of any of the attributes is not found: attrgetter('x.y', default=7)(None) => 7 BTW: This is inspired from Clojure's get-in (http://bit.ly/GGzqjh) function.

Kent Bower

unread,
Feb 11, 2015, 9:02:46 AM2/11/15
to python...@googlegroups.com
Recipe for building your own:

def attrgetter_default(*attrs, **kw):
    """
    Like attrgetter, but defaults to None (or specified default) if attr
    doesn't exist.
    Always returns tuple, even if only one in attrs (unlike attrgetter)
    """
    default = kw.pop('default', None)
    if kw:
        raise TypeError("attrgetter_default() got unexpected "
            "keyword argument(s): %r" % sorted(kw))
    def fn(obj):
        getter = lambda attr: getattr(obj, attr, default)
        return tuple(map(getter, attrs))
    return fn

You'd have to fix the behavior for a single attr if you want it to mimic attrgetter more closely, but that is the general idea.

>>> attrgetter_default('x', 'y', '__str__', default=7)(None)
(7, 7, <method-wrapper '__str__' of NoneType object at 0x2b7237171f90>)
Reply all
Reply to author
Forward
0 new messages