[Tutor] Coercion of user-defined numeric types - when does it happen?

Yigal Duppen yduppen@xs4all.nl
Sun, 30 Jun 2002 12:50:09 +0200


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

I'm trying to emulate a numeric type by implementing a Fraction class. I've 
followed chapter 3.3.6 of the reference manual, but I can't get 'mixed-mode' 
numeric arithmetic to work -- the interpreter does not automatically coerce 
the arguments.

To compress the problem a bit: my Fraction class has an __add__ and a 
__coerce__ method. __add__ works perfectly with other Fractions:

>>> print Fraction(1,3) + Fraction(1,4)
7/12

>>> print Fraction(1,4) + 1
????

What I _expect_ to happen is the following:
1) the interpreter calls Fraction.__add__ and realizes this does not work
2) the interpreter applies the different coercion rules specified in chap 
3.3.6
3) following the __coerce__ method, the interpreter then tries to print 
Fraction(1,4) + Fraction(1,1)

Unfortunately, step 1 is not fully specified -- how do I tell the interpreter 
that it should start coercing? 

For your convenience, I've inlined (a condensed version of) the Fraction 
class, together with a small test.

=================

def _gcd(a, b): 
    while b != 0:
        a, b = b, a%b
    return a

class Fraction(object):

    def __init__(self, numerator, denominator):
        # normalize values
        gcd = _gcd(numerator, denominator)
        self.num = numerator/gcd
        self.den = denominator/gcd

    def __add__(self, other):
        try:
            num = self.num * other.den + self.den * other.num
            den = self.den * other.den
            return Fraction(num, den)
        except AttributeError:
            # no fraction, other should be coerced... How do I tell
            # the interpreter to do this??? 
            pass

    def __coerce__(self, other):
        if type(other) is int:
            return (self, Fraction(other, 1))

        if type(other) is long:
            return (self, Fraction(other, 1))

        # Auto-convert self to type of other
        return None

    def __str__(self):
        return "%d/%d" % (self.num, self.den)


if __name__ == "__main__":
    print Fraction(1,3) + Fraction(2,1)
    print Fraction(1,3) + 2

===================

So how would I get the second line to work? (apart from implementing the 
entire coercion algorithm myself).

Thanks in advance,

YDD
- -- 
.sigmentation Fault
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE9HuJhLsKMuCf5EdwRAiqxAKCEIj9mPz+A/1VmyJFT8aCRjB1BeACeN+49
artL21ggSOwwWv5xBxQ1XEs=
=/KrX
-----END PGP SIGNATURE-----