[Tutor] Re: Another aftermath (Stern-Brocot tree):

Kirby Urner urnerk@qwest.net
Wed, 09 Jan 2002 06:51:11 -0800


>
>3. Could you please explain this remark a little bit:
>
> > As of 2.2, I think we do have class methods -- no need
> > for an instance in order for the method to work.

See below re staticmethod().

>Is the gcd in the F-class something like this?

F-class could be rewritten this way.  But since
every F needs a self (has its own numerator and
denominator), it's fine to not.  All instances
point back to the same code, so it's not like each
instance internally has its own copy of the methods.

However, ith gcd and lcm, you have the option to move
them out of the F class altogether and just define
them in the same module as the F-class.  When the
F-class uses them, it'll just say gcd(a,b) without
the self.gcd(a,b) in front.  This gives users
direct access to lcm and gcd without needing to
refer to any F.

>Even when using it inside F we need a self. ...
>to call ist. And could we call this from outside
>the class without an instance?
>( F.gcd(..., ...) as one might expect if it were similar
>to Java, does not work. )
>
>Sincerely
>Gregor

This'll work if we go:

   class F:

        def __init__(self,numer,denom):
           # reduce inputs to lowest terms
           gcd = F.gcd(numer,denom)
           self.num = numer//gcd
           self.den = denom//gcd

        def __add__(self,other):
            # find lowest common multiple
            a,b = self.num, other.num
            comden = F.lcm(self.den, other.den)
            if comden != self.den:
               a *= comden//self.den
            if comden != other.den:
               b *= comden//other.den
            return F(a+b,comden)

        def gcd(a,b):
            # find greatest common divisor of a,b
            if b==0: return a
            else: return F.gcd(b,a%b)

        def lcm(a,b):
            # find lowest common multiple of a,b
            return a*b//F.gcd(a,b)

        def __repr__(self):
            # represent as (a/b)
            return "(%s/%s)" % (self.num, self.den)

        gcd = staticmethod(gcd)
        lcm = staticmethod(lcm)

With instances:

  >>> a = F(1,2)
  >>> b = F(2,3)
  >>> a+b
  (7/6)

Without:

  >>> F.gcd(10,45)
  5
  >>> F.lcm(10,45)
  90

Note, to make your F-class even more versatile,
you could define how to multiply two fractions,
and how to raise fractions to integral powers,
i.e. define __mul__ and __pow__.  You could also
divide fractions by overriding __div__ -- which
comes in handy of the integral power is negative
i.e. (1/2)**-1 = 2/1 and (1/2)**-2 =
[2/1]**2 i.e. (p/q)**(-n) = (q/p)**n.

Kirby