class inheritance

Discussion in 'Python' started by JLundell, Mar 13, 2010.

  1. JLundell

    JLundell Guest

    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?
    JLundell, Mar 13, 2010
    #1
    1. Advertising

  2. On Mar 13, 11:03 am, JLundell <> 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?


    7 years ago, I had a similar problem for a different and now obsolete
    reason. I'm sure my solution could be easily updated though. I wrote
    code to write a wrapper class. Sort of a meta-module. Original
    reference here:

    http://groups.google.com/group/comp...en&lnk=gst&q=pmaupin userint#59289c16603fb374

    HTH,
    Pat
    Patrick Maupin, Mar 13, 2010
    #2
    1. Advertising

  3. On Sat, Mar 13, 2010 at 12:03 PM, JLundell <> 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?


    If Fraction.__add__ returns a new object but the subclass Value is
    compatible (as I would except since it is a sublcass) then just change
    all references in Franction.__add__ to be more generic, ex/

    class Franction():
    def __add__(self, other):
    return self.__classs__(self.denominator + other.denominator)

    That way if __add__ is called by an instance of a subclass it will
    return an instance of that subclass.

    -Jack
    Jack Diederich, Mar 13, 2010
    #3
  4. On Mar 13, 11:37 am, Jack Diederich <> wrote:
    > If Fraction.__add__ returns a new object but the subclass Value is
    > compatible (as I would except since it is a sublcass) then just change
    > all references in Franction.__add__ to be more generic, ex/
    >
    > class Franction():
    >   def __add__(self, other):
    >     return self.__classs__(self.denominator + other.denominator)
    >
    > That way if __add__ is called by an instance of a subclass it will
    > return an instance of that subclass.
    >


    Yes, I think the OP understands that, and also understands that he
    would have to do the same thing for __sub__, __div__, __rsub__,
    __radd__, etc.

    That's why I suggested that, instead of writing all that tedious code,
    he could write code that writes the tedious code :)

    As Terence Parr of ANTLER fame asks: "Why program by hand in five
    days what you can spend five years of your life automating?"

    Pat
    Patrick Maupin, Mar 13, 2010
    #4
  5. JLundell

    JLundell Guest

    On Mar 13, 9:37 am, Jack Diederich <> wrote:
    > If Fraction.__add__ returns a new object but the subclass Value is
    > compatible (as I would except since it is a sublcass) then just change
    > all references in Franction.__add__ to be more generic, ex/
    >
    > class Franction():
    >   def __add__(self, other):
    >     return self.__classs__(self.denominator + other.denominator)
    >
    > That way if __add__ is called by an instance of a subclass it will
    > return an instance of that subclass.


    That was my first thought, because I had originally assumed that's the
    way Fraction worked. However, a) it's easier to do the overriding in
    my own class than patching Fraction (or at least no harder), and 2)
    Fraction is only doing the same thing that int does, so it's hard to
    justify a patch.

    I think Patrick's solution might be the tidiest one. I'll give it a
    shot (thanks, Patrick).
    JLundell, Mar 13, 2010
    #5
  6. JLundell

    Carl Banks Guest

    On Mar 13, 9:03 am, JLundell <> 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
    Carl Banks, Mar 13, 2010
    #6
  7. JLundell 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?
    >

    I would change the approach.
    To the question, "*is* a Value a Fraction", some may tempted to answer
    "No" (for instance, a fraction has a denominator, a value has not).
    However "Does a Fraction *have* a Value", you could possibly say "Yes".

    The value may be then an attribute of the class Fraction, not a subclass.
    To test fraction equality, use F1 == F2. In order to test 'nearly
    equality', use F1.val() == F2.val().

    JM
    Jean-Michel Pichavant, Mar 15, 2010
    #7
  8. JLundell

    JLundell Guest

    On Mar 13, 1:26 pm, Carl Banks <> wrote:
    > 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


    It's also unfortunate that Python doesn't have an approximately-equal
    operator; it'd come in handy for floating-point applications while
    preserving hash. If only there were a ~= or ≈ operator I could
    overload. And ~ is unary, so no joy.

    My application is in that sense a little like a floating-point app, in
    that it needs approximately-equal. And it doesn't need Value to be
    hashable; thanks for the NotImplementedError suggestion; I've done
    that as a safeguard.
    JLundell, Mar 15, 2010
    #8
  9. JLundell

    Carl Banks Guest

    On Mar 15, 4:34 pm, JLundell <> wrote:
    > It's also unfortunate that Python doesn't have an approximately-equal
    > operator; it'd come in handy for floating-point applications while
    > preserving hash. If only there were a ~= or ≈ operator I could
    > overload. And ~ is unary, so no joy.


    One problem with it is that there's no way to make it universal;
    different appiplications have different ideas of close. Conceivably
    it could be usefully defined for a user type though..

    Bacause of this problem almost no languages have an almost equal
    operator. I'm curious what languages do, of if there are any with a
    trinary operator that also takes a threshold.

    Carl Banks
    Carl Banks, Mar 16, 2010
    #9
  10. JLundell

    Dave Angel Guest

    Carl Banks wrote:
    > On Mar 15, 4:34 pm, JLundell <> wrote:
    >
    >> It's also unfortunate that Python doesn't have an approximately-equal
    >> operator; it'd come in handy for floating-point applications while
    >> preserving hash. If only there were a ~=r ≈ operator I could
    >> overload. And ~ is unary, so no joy.
    >>

    >
    > One problem with it is that there's no way to make it universal;
    > different appiplications have different ideas of close. Conceivably
    > it could be usefully defined for a user type though..
    >
    > Bacause of this problem almost no languages have an almost equal
    > operator. I'm curious what languages do, of if there are any with a
    > trinary operator that also takes a threshold.
    >
    > Carl Banks
    >
    >

    If I recall correctly, APL has a *fuzz* value, which is used in all(?)
    comparisons. But I do not recall anything about how it was defined. I do
    recall that you could change the threshold, and suspect it was relative
    to the operands. For symmetry, it would probably have to be relative to
    the average of the two values, or some such.
    Dave Angel, Mar 16, 2010
    #10
  11. JLundell

    Robert Kern Guest

    On 2010-03-16 07:35 AM, Dave Angel wrote:
    >
    >
    > Carl Banks wrote:
    >> On Mar 15, 4:34 pm, JLundell <> wrote:
    >>> It's also unfortunate that Python doesn't have an approximately-equal
    >>> operator; it'd come in handy for floating-point applications while
    >>> preserving hash. If only there were a ~=r ≈ operator I could
    >>> overload. And ~ is unary, so no joy.

    >>
    >> One problem with it is that there's no way to make it universal;
    >> different appiplications have different ideas of close. Conceivably
    >> it could be usefully defined for a user type though..
    >>
    >> Bacause of this problem almost no languages have an almost equal
    >> operator. I'm curious what languages do, of if there are any with a
    >> trinary operator that also takes a threshold.
    >>
    >> Carl Banks
    >>

    > If I recall correctly, APL has a *fuzz* value, which is used in all(?)
    > comparisons. But I do not recall anything about how it was defined. I do
    > recall that you could change the threshold, and suspect it was relative
    > to the operands. For symmetry, it would probably have to be relative to
    > the average of the two values, or some such.


    The problem is that frequently there is no system-wide fuzz value which is
    appropriate for all comparisons in a given program. You need to choose the right
    value for each comparison. Consequently, you might as well use a function
    instead of an operator and a global variable.

    --
    Robert Kern

    "I have come to believe that the whole world is an enigma, a harmless enigma
    that is made terrible by our own mad attempt to interpret it as though it had
    an underlying truth."
    -- Umberto Eco
    Robert Kern, Mar 16, 2010
    #11
  12. JLundell

    JLundell Guest

    On Mar 16, 8:06 am, Robert Kern <> wrote:
    > On 2010-03-16 07:35 AM, Dave Angel wrote:
    >
    >
    >
    >
    >
    >
    >
    > > Carl Banks wrote:
    > >> On Mar 15, 4:34 pm, JLundell <> wrote:
    > >>> It's also unfortunate that Python doesn't have an approximately-equal
    > >>> operator; it'd come in handy for floating-point applications while
    > >>> preserving hash. If only there were a ~=r ≈ operator I could
    > >>> overload. And ~ is unary, so no joy.

    >
    > >> One problem with it is that there's no way to make it universal;
    > >> different appiplications have different ideas of close. Conceivably
    > >> it could be usefully defined for a user type though..

    >
    > >> Bacause of this problem almost no languages have an almost equal
    > >> operator. I'm curious what languages do, of if there are any with a
    > >> trinary operator that also takes a threshold.

    >
    > >> Carl Banks

    >
    > > If I recall correctly, APL has a *fuzz* value, which is used in all(?)
    > > comparisons. But I do not recall anything about how it was defined. I do
    > > recall that you could change the threshold, and suspect it was relative
    > > to the operands. For symmetry, it would probably have to be relative to
    > > the average of the two values, or some such.

    >
    > The problem is that frequently there is no system-wide fuzz value which is
    > appropriate for all comparisons in a given program. You need to choose the right
    > value for each comparison. Consequently, you might as well use a function
    > instead of an operator and a global variable.
    >
    > --
    > Robert Kern
    >


    APL scaled their fuzz to the larger of the values being compared. In
    my case, my domain permits me to use a constant fuzz; all my units are
    the same (votes, as it happens). I've seen abs(a/b-1) used instead of
    abs(a-b); obviously you'd need to treat comparison with zero
    specially.

    But yeah, it's really a domain-specific problem.
    JLundell, Mar 16, 2010
    #12
  13. JLundell

    Robert Kern Guest

    On 2010-03-16 17:55 PM, JLundell wrote:
    > On Mar 16, 8:06 am, Robert Kern<> wrote:
    >> On 2010-03-16 07:35 AM, Dave Angel wrote:
    >>
    >>> Carl Banks wrote:
    >>>> On Mar 15, 4:34 pm, JLundell<> wrote:
    >>>>> It's also unfortunate that Python doesn't have an approximately-equal
    >>>>> operator; it'd come in handy for floating-point applications while
    >>>>> preserving hash. If only there were a ~=r ≈ operator I could
    >>>>> overload. And ~ is unary, so no joy.

    >>
    >>>> One problem with it is that there's no way to make it universal;
    >>>> different appiplications have different ideas of close. Conceivably
    >>>> it could be usefully defined for a user type though..

    >>
    >>>> Bacause of this problem almost no languages have an almost equal
    >>>> operator. I'm curious what languages do, of if there are any with a
    >>>> trinary operator that also takes a threshold.

    >>
    >>>> Carl Banks

    >>
    >>> If I recall correctly, APL has a *fuzz* value, which is used in all(?)
    >>> comparisons. But I do not recall anything about how it was defined. I do
    >>> recall that you could change the threshold, and suspect it was relative
    >>> to the operands. For symmetry, it would probably have to be relative to
    >>> the average of the two values, or some such.

    >>
    >> The problem is that frequently there is no system-wide fuzz value which is
    >> appropriate for all comparisons in a given program. You need to choose the right
    >> value for each comparison. Consequently, you might as well use a function
    >> instead of an operator and a global variable.
    >>
    >> --
    >> Robert Kern
    >>

    >
    > APL scaled their fuzz to the larger of the values being compared.


    I know. My statement stands for relative fuzz values as well as it does for
    absolute fuzz values. :)

    > In
    > my case, my domain permits me to use a constant fuzz; all my units are
    > the same (votes, as it happens). I've seen abs(a/b-1) used instead of
    > abs(a-b); obviously you'd need to treat comparison with zero
    > specially.


    One usually uses a combination of relative and absolute tolerances to account
    for the case when the values are close to zero.

    > But yeah, it's really a domain-specific problem.


    Right. And a single program might need to deal with multiple domains, so a
    single global setting to control a language feature is pretty fragile.

    --
    Robert Kern

    "I have come to believe that the whole world is an enigma, a harmless enigma
    that is made terrible by our own mad attempt to interpret it as though it had
    an underlying truth."
    -- Umberto Eco
    Robert Kern, Mar 16, 2010
    #13
  14. On Tue, 16 Mar 2010 07:35:54 -0500, Dave Angel <>
    declaimed the following in gmane.comp.python.general:


    > If I recall correctly, APL has a *fuzz* value, which is used in all(?)
    > comparisons. But I do not recall anything about how it was defined. I do
    > recall that you could change the threshold, and suspect it was relative
    > to the operands. For symmetry, it would probably have to be relative to
    > the average of the two values, or some such.


    I didn't do enough with APL back in 1980 to get to that point (I
    needed 2 credits to graduate, so took a 3 credit independent study of
    APL -- where my biggest program was to turn a Tektronix storage display
    terminal into the worlds most expensive Etch-a-Sketch)

    REXX has a similar (from the Regina manual):

    """
    The NUMERIC statement is used to control most aspects of arithmetic
    operations. It has three distinct forms: DIGITS, FORM and FUZZ; which to
    choose is given by the second token in the instruction:

    DIGITS
    Is used to set the number of significant digits in arithmetic
    operations. The initial value is 9, which is also the default value if
    expr is not specified. Large values for DIGITS tend to slow down some
    arithmetic operations considerably. If specified, expr must be a
    positive integer.

    FUZZ
    Is used in numeric comparisons, and its initial and default value is
    0. Normally, two numbers must have identical numeric values for a number
    of their most significant digits in order to be considered equal. How
    many digits are considered is determined by DIGITS. If DIGITS is 4, then
    12345 and 12346 are equal, but not 12345 and 12356. However, when FUZZ
    is nonzero, then only the DIGITS minus FUZZ most significant digits are
    checked. E.g. if DIGITS is 4 and FUZZ are 2, then 1234 and 1245 are
    equal, but not 1234 and 1345.
    The value for FUZZ must be a nonnegative integer, and less than the
    value of DIGITS. FUZZ is seldom used, but is useful when you want to
    make comparisons less influenced by inaccuracies. Note that using with
    values of FUZZ that is close to DIGITS may give highly surprising
    results.
    """
    --
    Wulfraed Dennis Lee Bieber KD6MOG
    HTTP://wlfraed.home.netcom.com/
    Dennis Lee Bieber, Mar 17, 2010
    #14
  15. On Mon, 15 Mar 2010 16:34:35 -0700, JLundell wrote:

    > It's also unfortunate that Python doesn't have an approximately-equal
    > operator; it'd come in handy for floating-point applications while
    > preserving hash. If only there were a ~= or ≈ operator I could overload.
    > And ~ is unary, so no joy.


    Not everything needs to be a built-in, or an operator. This might be
    useful for you:

    http://code.activestate.com/recipes/577124-approximately-equal/


    Feedback welcome.


    --
    Steven
    Steven D'Aprano, Mar 18, 2010
    #15
  16. JLundell

    JLundell Guest

    On Mar 17, 5:12 pm, Steven D'Aprano
    <> wrote:
    > On Mon, 15 Mar 2010 16:34:35 -0700,JLundellwrote:
    > > It's also unfortunate that Python doesn't have an approximately-equal
    > > operator; it'd come in handy for floating-point applications while
    > > preserving hash. If only there were a ~= or ≈ operator I could overload.
    > > And ~ is unary, so no joy.

    >
    > Not everything needs to be a built-in, or an operator. This might be
    > useful for you:
    >
    > http://code.activestate.com/recipes/577124-approximately-equal/
    >
    > Feedback welcome.
    >
    > --
    > Steven


    Thanks, Steven. I'd considered and rejected that a while ago, but on
    reconsideration it's sounding like a better idea. Aside from
    preserving the semantics of =, it makes the use of approximate
    equality explicit in the code, and that's a plus for what I'm doing.
    I'll give it a shot.
    JLundell, Mar 18, 2010
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. maxw_cc
    Replies:
    1
    Views:
    3,136
    Martijn van Steenbergen
    Dec 21, 2003
  2. E11
    Replies:
    1
    Views:
    4,737
    Thomas Weidenfeller
    Oct 12, 2005
  3. cppsks
    Replies:
    0
    Views:
    815
    cppsks
    Oct 27, 2004
  4. karthikbalaguru
    Replies:
    9
    Views:
    1,036
  5. johnsonlau
    Replies:
    1
    Views:
    769
    Kai-Uwe Bux
    Jul 21, 2008
Loading...

Share This Page