[Python-ideas] comparison of operator.itemgetter objects

Max Moroz maxmoroz at gmail.com
Mon Apr 2 10:30:26 CEST 2012


Currently, __eq__() method is not defined in class operator.itemgetter,
hence non-identical itemgetter objects compare as non-equal.

I wanted to propose defining __eq__() method that would return the result
of comparison for equality of the list of arguments submitted at
initialization. This would make operator.itemgetter('name') compare as
equal to operator.itemgetter('name').

The motivation for this is that sorted data structure (such as
blist.sortedset) might want to verify if two arguments (say, lhs and rhs)
of a binary operation (such as union) have the same sort key (a callable
object passed to the constructor of the sorted data structure). Such a
verification is useful because the desirable behavior of such binary
operations is to use the common sort key if the lhs and rhs have the same
sort key; and to raise an exception (or at least use a default value of the
sort key) otherwise.

I think that comparing sort keys for equality works well in many useful
cases:

(a) Named function. These compare as equal only if they are identical. If
lhs and rhs were initialized with distinct named functions, I would argue
that the programmer did not intend them to be compatible for the purpose of
binary operations, even if they happen to be identical in behavior (e.g.,
if both functions return back the argument passed to them). In a
well-designed program, there is no need to duplicate the named function
definition if the two are expected to always have the same behavior.
Therefore, the two distinct functions are intended to be different in
behavior at least in some situations, and therefore the sorted data
structure objects that use them as keys should be considered incompatible.

(b) User-defined callable class. The author of such class should define
__eq__() in a way that would compare as equal callable objects that behave
identically, assuming it's not prohibitively expensive.

Unfortunately, in two cases comparing keys for equality does not work well.

(c) itemgetter. Suppose a programmer passed `itemgetter('name')` as the
sort key argument to the sorted data structure's constructor. The resulting
data structures would seem incompatible for the purposes of binary
operations. This is likely to be confusing and undesirable.

(d) lambda functions. Similarly, suppose a programmer passed `lambda x :
-x` as the sort key argument to the sorted data structure's constructor.
Since two lambda functions are not identical, they would compare as
unequal.

It seems to be very easy to address the undesirable behavior described in
(c): add method __eq__() to operator.itemgetter, which would compare the
list of arguments received at initialization. This would only break code
that relies on an undocumented fact that distinct itemgetter instances
compare as non-equal.

The alternative is for each sorted data structure to handle this comparison
on its own. This is repetitive and error-prone. Furthermore, it is
expensive for an outsider to find out what arguments were given to an
itemgetter at initialization.

It is far harder to address the undesirable behavior described in (d). If
it can be addressed at all, it would have to done in the sorted data
structure implementation, since I don't think anyone would want lambda
function comparison behavior to change. So for the purposes of this
discussion, I ignore case (d).

Is this a reasonable idea? Is it useful enough to be considered? Are there
any downsides I didn't think of? Are there any other callables created by
Python's builtin or standard library functions where __eq__ might be useful
to define?

Thanks,

Max
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20120402/ca54f51f/attachment.html>


More information about the Python-ideas mailing list