class inheritance

Carl Banks pavlovevidence at gmail.com
Sat Mar 13 21:26:45 CET 2010


On Mar 13, 9:03 am, JLundell <jlund... at pobox.com> wrote:
> I've got a subclass of fractions.Fraction called Value; it's a mostly
> trivial class, except that it overrides __eq__ to mean 'nearly equal'.
> However, since Fraction's operations result in a Fraction, not a
> Value, I end up with stuff like this:
>
> x = Value(1) + Value(2)
>
> where x is now a Fraction, not a Value, and x == y uses
> Fraction.__eq__ rather than Value.__eq__.
>
> This appears to be standard Python behavior (int does the same thing).
> I've worked around it by overriding __add__, etc, with functions that
> invoke Fraction but coerce the result. But that's tedious; there are a
> lot of methods to override.
>
> So I'm wondering: is there a more efficient way to accomplish what I'm
> after?

It's a tad unfortunately Python doesn't make this easier.  If I had to
do it more than once I'd probably write a mixin to do it:

class ArithmeticSelfCastMixin(object):
    def __add__(self,other):
        return
self.__class__(super(ArithmeticSelfCastMixin,self).__add__(other)
    # etc.


class Value(ArithmeticSelfCastMixin,fraction.Fraction):
    pass


However, I want to warn you about overriding __eq__ to mean "almost
equal": it can have unexpected results so I don't recommend it.  Two
of the main issues with it are:

1. It violates the transitive property ("If A == B and B == C, then A
== C") which most programmers expect to be true.

2. It will give unpredictable results when the objects are used in
sets or as dictionary keys.  Those thow types expect the transitive
property to be true.  If you are going to redefine __eq__ to mean
"almost equal", then at least define __hash__ to raise
NotImplementedError so that Python will refuse to use them in sets or
as dictionary keys:

    def __hash__(self): raise NotImplementedError


Carl Banks



More information about the Python-list mailing list