[issue14384] Add "default" kw argument to operator.itemgetter and operator.attrgetter

Raymond Hettinger report at bugs.python.org
Sat May 5 17:35:58 EDT 2018


Raymond Hettinger <raymond.hettinger at gmail.com> added the comment:

Here are a few more thoughts and a concrete example for clarity.

Itemgetter/Attrgetter were designed to make multiple lookups (possibly multi-level) and to return a tuple that need not be homogenous.  A single default value likely doesn't make sense in any of those contexts. 

Consider:

    attrgetter('programmer.lang', 'team.dept')

Various behaviors you might want:

    (o.programmer.lang if hasattr(o, 'programmer') else o.avg_joe.lang, o.team.dept)

    (o.programmer.lang if hasattr(o.programmer) else 'python', o.team.dept)

    (o.programmer.long, o.team.dept if hasattr(o.team, 'dept') else 'accounting')

    try:
        return (o.programmer.lang, o.team.dept)
    except AttributeError:
        return ('python', 'accounting')

Other than the OP's example with a universal default value of None (which would like require more tests downstream), I can't think of any meaningful default value that would apply to both programmer.lang and team.dept.

If this proposal is to go forward, its needs a more informative use case than the toy example provided on python-ideas:
                
    p1 = {'x': 43; 'y': 55} 
    x, y, z = itemgetter('x', 'y', 'z', default=0)(values) 
    print(x, y, z) 
    43, 55, 0 

And if it does go forward, I would suggest that the semantics of default be an entire result tuple rather than a scalar applied on an attribute by attribute basis:

    attrgetter('programmer.lang', 'team.dept', default=('python', 'accounting'))
    attrgetter('temperature', 'humidity', 'altitude', default=('22°C', '50%', "0 meters MSL"))
    attrgetter('foo', default=None)

That would still meet the OP's use case, but would be more broadly applicable and not make the assumption that every field has the same default value.  

Even with that improvement, users would still likely be better-off writing a function that explicitly says what they want to do.  For example, the OP's use case can already be written like this:

    get = lambda obj:  getattr(obj, 'foo', None)
    return get(args) or get(config) or get(env)

That is easy and unambiguous.  Writing a separate function allows all of the above cases to be written cleanly.  There isn't any need to trick-out itemgetter() for this.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue14384>
_______________________________________


More information about the Python-bugs-list mailing list