[Edu-sig] Algebra + Python

Kirby Urner pdx4d@teleport.com
Sun, 6 May 2001 20:12:58 -0700


> = Ka-Ping Yee
  = Kirby

> Python has a built-in function "isinstance" to help you do this.

Yes, that cleans up my syntax quite a bit.  I'd played around
with isinstance before and drew some wrong conclusions -- it's
more useful than I'd realized.

The only advantage of doing it the other way is my pyfractions module 
could remain ignorant of Poly and Matrix objects and yet still refer 
back to their methods: i.e. n.__class__.__name__ == "Matrix" can be 
truth-tested without the global name Matrix having any meaning in 
this module (pyfraction).  But it's a very small price to pay to put:  
from simplematrix import Matrix (and similar for Poly) at the top
(since I'm testing for these kinds of object, I might as well make
this module aware of them).  

Note: I've also added Sqmatrix as a subclass of Matrix (for square
matrices), as so many matrix ops only make sense when applied to
square matrices.

> In addition, my personal preference would be to simply use *
> instead of calling __mul__ explicitly, although that's more of
> a style issue.  Anyway here's what i would write:

I was hesitant to do this because the reason I'm in Fraction's 
__mul__ method in the first place is the Matrix or Poly __mul__ 
method was ignored in favor of Fraction's in some "poly * fraction"
or "fraction * matrix" type expression.

By putting: print -> "Fraction" in Fraction's __mul__, I can
see when it's being called:

  >>> I = Sqmatrix([[1,0,0],[0,1,0],[0,0,1]])
  >>> f = Fraction(1,2)
  >>> f*I
  -> Fraction
  [(1/2), 0, 0]
  [0, (1/2), 0]
  [0, 0, (1/2)]

  >>> I*f
  [(1/2), 0, 0]
  [0, (1/2), 0]
  [0, 0, (1/2)]

So Fraction is trapping these cases and forcing us to use the 
passed object's __mul__ method instead of Fraction's.  I was 
thinking that using * in place of n.__mul__ might just trigger 
a repeat of the same situation (i.e. might beget the same 
ambiguity I'm coding to avoid).... But so far, going with * 
is working OK.  You must have clearer insight into this issue, 
or at least aren't quite so confused.  Is it the case that 
__mul__ always takes precedence over __rmul__ if both are
defined?  That would explain the above I think.

> 
>     class Fraction:
>         ...
>         def __mul__(self, n):
>             if isinstance(n, Poly) or isinstance(n, Matrix):
>                 return n * self
>             f = self.mkfract(n)
>             return Fraction(self.numer * f.numer, self.denom 
> * f.denom)
> 
> Very nice work, by the way!

Thanks.  I appreciate the tips -- thanks to which, I'm gradually
getting more proficient with this nifty language.

> 
> -- ?!ng

Kirby