[Python-Dev] Should the default equality operator compare values instead of identities?

Josiah Carlson jcarlson at uci.edu
Sat Nov 5 21:30:17 CET 2005


Noam Raphael <noamraph at gmail.com> wrote:
> On 11/3/05, Josiah Carlson <jcarlson at uci.edu> wrote:
> > > To summarize, I think that value-based equality testing would usually
> > > be what you want, and currently implementing it is a bit of a pain.
> >
> > Actually, implementing value-based equality testing, when you have a
> > finite set of values you want to test, is quite easy.
> >
> > def __eq__(self, other):
> >     for i in self.__cmp_eq__:
> >         if getattr(self, i) != getattr(other, i):
> >             return False
> >     return True
> >
> > With a simple metaclass that discovers all of those values automatically,
> > and/or your own protocol for exclusion, and you are done.  Remember, not
> > all 5-line functions should become builtin/default behavior, and this
> > implementation shows that it is not a significant burdon for you (or
> > anyone else) to implement this in your own custom library.
> >
> You are right that not all 5-line functions should become
> builtin/default behaviour. However, I personally think that this one
> should, since:
> 1. It doesn't add complexity, or a new builtin.

It changes default behavior (which I specified as a portion of my
statement, which you quote.

And you are wrong, it adds complexity to the implementation of both
class instantiation and the default comparison mechanism.  The former, I
believe, you will find more difficult to patch than the comparison,
though if you have not yet had adventures in that which is writing C
extension modules, modifying the default class instantiation may be
the deal breaker for you (I personally would have no idea where to start).


> 2. Those five line doesn't include the metaclass code, which will
> probably take more than five lines and won't be trivial.

class eqMetaclass(type):
    def __new__(cls, name, bases, dct):
        if '__cmp_include__' in dct:
            include = dict.fromkeys(dct['__cmp_include__'])
        else:
            include = dict.fromkeys(dct.keys)

        for i in dct.get('__cmp_exclude__'):
            _ = include.pop(i, None)

        dct['__cmp_eq__'] = include.keys()
        return type.__new__(cls, name, bases, dct)

It took 10 lines of code, and was trivial (except for not-included
multi-metaclass support code, which is being discussed in another thread).

Oh, I suppose I should modify that __eq__ definition to be smarter about
comparison...

def __eq__(self, other):
    if not hasattr(other, '__cmp_eq__'):
        return False
    if dict.fromkeys(self.__cmp_eq__) != \
       dict.fromkeys(other.__cmp_eq__):
        return False
    for i in self.__cmp_eq__:
        if getattr(self, i) != getattr(other, i):
            return False
    return True

Wow, 20 lines of support code, how could one ever expect users to write
that? ;)


> 3. It will make other objects behave better, not only mine - other
> classes will get a meaningful comparison operator, for free.

You are that the comparison previously wasn't "meaningful".  It has a
meaning, though it may not be exactly what you wanted it to be, which is
why Python allows users to define __eq__ operators to be exactly what
they want, and which is why I don't find your uses compelling.


> > P.S. One thing that you should remember is that even if your patch is
> > accepted, and even if this is desireable, Python 2.5 is supposed to be
> > released sometime next year (spring/summer?), and because it is a
> > backwards incompatible change, would need at least 2.6-2.7 before it
> > becomes the default behavior without a __future__ import, which is
> > another 3-4 years down the line.
> 
> I hope that the warning can go in by Python 2.5, so the change (which
> I think will cause relatively few backwards incompatibility problems)
> can go in by Python 2.6, which I think is less than 2 years down the
> line.

As per historical release schedules (available in PEP form at
www.python.org/peps), alpha 1 to final generally takes 6 months.  It
then takes at least a year before the alpha 1 of the following version
is to be released.

Being that 2.4 final was released November 2004, and we've not seen an
alpha for 2.5 yet, we are at least 6 months (according to history) from
2.5 final, and at least 2 years from 2.6 final.

From what I have previously learned from others in python-dev, the
warnings machinery is slow, so one is to be wary of using warnings
unless absolutely necessary. Regardless of it being absolutely necessary,
it would be 2 years at least before the feature would actually make it
into Python and become default behavior, IF it were desireable default
behavior.


> Thanks - I should really calm down a bit. I will try to go "safe and
> slowly", and I hope that at the end I will succeed in making my own
> small contribution to Python.

You should also realize that you can make contributions to Python
without changing the language or the implementation of the langauge. 
Read and review patches, help with bug reports, hang out on python-list
and attempt to help the hundreds (if not thousands) of users who are
asking for help, try to help new users in python-tutor, etc.  If you
have an idea for a language change, offer it up on python-list first
(I've forgotten to do this more often than I would like to admit), and
if it generally has more "cool" than "ick", then bring it back here.

 - Josiah



More information about the Python-Dev mailing list