On 2012-09-14, at 13:01 , Nick Coghlan wrote:It was my understanding that they are also designed to be useful for
> On Thu, Sep 13, 2012 at 11:15 PM, Masklinn <mask...@masklinn.net> wrote:
>> attrgetter and itemgetter are both very useful functions, but both have
>> a significant pitfall if the arguments passed in are validated but not
>> controlled: if receiving the arguments (list of attributes, keys or
>> indexes) from an external source and *-applying it, if the external
>> source passes a sequence of one element both functions will in turn
>> return an element rather than a singleton (1-element tuple).
>
> Both attrgetter and itemgetter are really designed to be called with
> *literal* arguments, not via *args. In particular, they are designed
> to be useful as arguments bound to a "key" parameter, where the object
> vs singleton tuple distinction doesn't matter.
mapping (such a usage is shown in itemgetter's examples), which is
a superset of the use case outlined here.
> If that behaviour is not desirable, *write a different function* that
> does what you want, and don't use itemgetter or attrgetter at all.
> These tools are designed as convenience functions
On Sep 14, 2012 10:02 PM, "Jim Jewett" <jimjj...@gmail.com> wrote:
>
> On 9/14/12, Oscar Benjamin <oscar.j....@gmail.com> wrote:
>
> > I can see why you would expect different behaviour here, though. I tend not
> > to think of the functions in the operator module as convenience functions
> > but as *efficient* nameable functions referring to operations that are
> > normally invoked with a non-function syntax. Which is more convenient out
> > of the following:
>
> > 1) using operator
> > import operator
> > result = sorted(values, key=operator.attrgetter('name'))
>
> I would normally write that as
>
> from operator import attrgetter as attr
> ... # may use it several times
>
> result=sorted(values, key=attr('name'))
>
> which is about the best I could hope for, without being able to use
> the dot itself.
To be clear, I wasn't complaining about the inconvenience of importing and referring to attrgetter. I was saying that if the obvious alternative (lambda functions) is at least as convenient then it's odd to describe itemgetter/attrgetter as convenience functions.
> > 2) using lambda
> > result = sorted(values, key=lambda v: v.name)
>
> And I honestly think that would be worse, even if lambda didn't have a
> code smell. It focuses attention on the fact that you're creating a
> callable, instead of on the fact that you're grabbing the name
> attribute.
I disagree here. I find the fact that a lambda function shows me the expression I would normally use to get the quantity I'm interested in makes it easier for me to read. When I look at it I don't see it as a callable function but as an expression that I'm passing for use somewhere else.
>
> > In general it is bad to conflate scalar/sequence semantics so that a caller
> > should get a different type of object depending on the length of a
> > sequence.
>
> Yeah, but that can't really be solved well in python, except maybe by
> never extending an API to handle sequences. I would personally not
> consider that an improvement.
>
> Part of the problem is that the cleanest way to take a variable number
> of arguments is to turn them into a sequence under the covers (*args),
> even if they weren't passed that way.
>
> -jJ
You can extend an API to support sequences by adding a new entry point. This is a common idiom in python: think list.append vs list.extend.
Oscar