<div class="gmail_quote">On 14 September 2012 12:36, Masklinn <span dir="ltr"><<a href="mailto:masklinn@masklinn.net" target="_blank">masklinn@masklinn.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On 2012-09-14, at 13:01 , Nick Coghlan wrote:<br>
> On Thu, Sep 13, 2012 at 11:15 PM, Masklinn <<a href="mailto:masklinn@masklinn.net">masklinn@masklinn.net</a>> wrote:<br>
>> attrgetter and itemgetter are both very useful functions, but both have<br>
>> a significant pitfall if the arguments passed in are validated but not<br>
>> controlled: if receiving the arguments (list of attributes, keys or<br>
>> indexes) from an external source and *-applying it, if the external<br>
>> source passes a sequence of one element both functions will in turn<br>
>> return an element rather than a singleton (1-element tuple).<br>
><br>
> Both attrgetter and itemgetter are really designed to be called with<br>
> *literal* arguments, not via *args. In particular, they are designed<br>
> to be useful as arguments bound to a "key" parameter, where the object<br>
> vs singleton tuple distinction doesn't matter.<br>
<br>
</div>It was my understanding that they are also designed to be useful for<br>
mapping (such a usage is shown in itemgetter's examples), which is<br>
a superset of the use case outlined here.<br>
<div class="im"><br>
> If that behaviour is not desirable, *write a different function* that<br>
> does what you want, and don't use itemgetter or attrgetter at all.<br>
> These tools are designed as convenience functions<br></div></blockquote><div><br></div><div>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:</div>
<div><br></div><div>1) using operator</div><div>import operator</div><div>result = sorted(values, key=operator.attrgetter('name'))</div><div><br></div><div>2) using lambda</div><div>result = sorted(values, key=lambda v: <a href="http://v.name">v.name</a>)</div>
<div><br></div><div>I don't think that the operator module is convenient and I think that it damages readability in many cases. My primary reason for choosing it in some cases is that it is more efficient than the lambda expression.</div>
<div><br></div><div>There is no special syntax for 'get several items as a tuple'. I didn't know about this extended use for attrgetter, itemgetter. I can't see any other functions in the operator module (abs, add, and_, ...) that extend the semantics of the operation they are supposed to represent in this way.</div>
<div><br></div><div>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. I can see how practicality beats purity in adding this feature for people who want to use these functions for sorting by a couple of elements/attributes. I think it would have been better though to add these as separate functions itemsgetter and attrsgetter that always return tuples.</div>
</div><br><div>Oscar</div>