Python keeps getting stuck on this line because there is no attribute "numerator" (and I'm assuming it'd say it has no attribute for denominator either).

    third = Rational(25, 10)
    print ("third: 0/1".format(third.numerator(), third.denominator()))

For my Rational class, I've got

def gcd(a, b):
    if b == 0:
        return a
    else:
        return gcd(b, a%b)

class Rational(object):
# we set a numerator and denominator, and simplify unless told otherwise
    def __init__(self, numerator, denominator = 1, simp = True):
# denominator can't be zero
        if denominator == 0:
            raise ZeroDivisionError("Denominator can't be zero.")

# if numerator and denominator are both integers, then this is pretty simple
        if isinstance(numerator, (int)) and isinstance(denominator, (int)):
            self.num = numerator
            self.den = denominator
# if the numerator is rational, we just multiply the den of it by the denominator passed to __init__
        elif isinstance(numerator, Rational) and (isinstance(denominator, int) or isinstance(denominator, long)):
            self.num = numerator.num
            self.den = numerator.den * denominator
# lastly, we deal with the case of the denominator being rational
        elif isinstance(denominator, Rational):
            self.num = (Rational(numerator) / (denominator)).num
            self.den = (Rational(numerator) / (denominator)).den
        else:
            raise TypeError("Numerator and denominator each have to be int, long, or Rational")
# let's get it in lowest terms
        if simp == True:
            self.simplify()

# see last comment
    def simplify(self):
        gcdivisor = gcd(self.num, self.den)
        self.num /= gcdivisor
        self.den /= gcdivisor
#      return self

    def __add__(self, other, simp=True):
        other = Rational(other)
        return Rational(other.den * self.num + self.den * other.num, self.den * other.den, simp)

    def __sub__(self, other, simp=True):
        other = Rational(other)
        other.num = -other.num
        return    self.__add__(other, simp)

# division
    def __div__(self, other, simp=True):
        other = Rational(other)
        return Rational(self.num * other.den, self.den * other.num, simp)

# multiplication
    def __mul__(self, other, simp=True):
        other = Rational(other)
        return Rational(self.num * other.num, self.den * other.den, simp)

# exponentiation
    def __pow__(self, other, simp=True):
        if isinstance(other, (float, Rational)):
            raise TypeError("stick to integeral exponents, please")
        if other >= 0:
            return Rational(self.num ** other, self.den ** other)
        elif other < 0:
            return Rational(self.den ** -other, self.num ** -other)

    def __pos__(self, other, simp=True):
        return self

    def __neg__(self, other, simp=True):
        return Rational(-self.num, self.den, simp)

    def __abs__(self, other, simp=True):
        return Rational(abs(self.num), abs(self.den))

    def __eq__(self, other):
        if not isinstance(other, float):
            other = Rational(other)
            return self.num == other.num and self.den == other.den
        else:
            return float(self) == other

    def __gt__(self, other):
        if not isinstance(other, float):
            return self.num * Rational(other).den > Rational(other).num * self.den

    def __lt__(self, other):
        return not (self > other or self == other)

    def __ge__(self, other):
        return self > other or self == other

    def __le__(self, other):
        return self < other or self == other

    def __float__(self):
      return float(self.num) / self.den

    def __int__(self):
      return self.num / self.den

    def __long__(self):
      return self.num / self.den

    def __repr__(self):
      return 'Rational(%s, %s)' % (self.num, self.den)

So I'm wondering where/how I have to put it in this class so that it'll work for the numerator/denominator attribute?

Recommended Answers

All 3 Replies

The interpreter cannot find those properties because you didn't define them; I assume this was simply an oversight. Happens all the time, no big worry there. Just add the following methods to the class:

    @property
    def numerator(self):
        return self.num

    @property
    def denominator(self):
        return self.den     

BTW, your string formatting should read:

print ("third: {0}/{1}".format(third.numerator(), third.denominator()))

HTH.

commented: thank you! +0

Changed what you said to add/change and now I get an error "TypeError: 'float' object is not callable" on the print ("third: {0}/{1}".format(third.numerator(), third.denominator())) line.

OK, that was a somewhat careless mistake on my part; it should have been

    print ("third: {0}/{1}".format(third.numerator, third.denominator))

without the parentheses (which is the whole point of using a property, after all). Sorry.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.