So I've been yakking with Ian (tizard.stanford.edu) re the new fractions.py, installed in Standard Library per 2.6, saw it demoed at a recent user group meeting (PPUG). Python's __div__ is similar to Mathematica's computer algebra notion of division in that you're free to divide any type by any type, providing this makes any algebraic sense, using a kind of liberal duck typing. What I mean by that is __div__ by itself doesn't pre-specify anything, so if there's a meaningful way to deploy the division operator between arguments A, B, then go ahead and do it, write you code accordingly. In Java, we could write __div__ in all different ways depending on valid type permutations (not that Java has operator overloading, just stricter typing at write time means you've gotta post "guards at the gate" in your methods). Python, with late binding, duck typing, won't post guards, but you'll still need to write algorithms capable of sorting out the possibilities. Maybe the user throws you a matrix? Has an inverse. OK, so __div__ makes some sense... fractions.py in contrast, implements the narrow Q type, the rational number, defined as p / q where p, q are members of the set integers. One could imagine a Fraction class that eats two complex numbers, or two Decimals. Computer algebra attaches meaning here, as in both sets we're able to define a multiplicative identity such that A / B means A * B**(-1) i.e. A * pow(B, -1) i.e. A * (1/B). So the results of this operation, Fraction(A, B), might be some object holding the Decimal or Complex result. In generic algebra, everything's a duck, although conversion between types is possible (yes, that sounds nonsensical). fractions.Fraction, on the other hand, barfs on anything but integers, isn't trying to be all divisions to all possible types, isn't pretending this is Mathematica or a generic CAS. Note that I'm not criticizing fractions.py in any way, am so far quite happy with it. I'm simply drawing attention to some fine points. Related: When I went to all the trouble to compose two functions, f and g, using __mul__, I'd get comments like: but the "open oh" (another symbol) is the "composition operator" i.e. "you're only using * because ASCII doesn't include the 'open oh'". However, I was making a different point: that in group theory math texts, we're proud to use "regular" multiplication and division operators for such operations as "compositions of functions" because we're thinking __mul__ and __div__ have that generic meaning -- we neither need, nor want, the proliferation of symbols the "open oh" people think we must need. Note that by "open oh" I'm not talking about "big oh", a different notation that I don't think is redundant, agree with Knuth that if your calculus book doesn't include it, you're probably in one of those computer illiterate schools (ETS slave, whatever). Kirby
On Wed, Dec 10, 2008 at 6:47 PM, kirby urner <kirby.urner@gmail.com> wrote:
So I've been yakking with Ian (tizard.stanford.edu) re the new fractions.py, installed in Standard Library per 2.6, saw it demoed at a recent user group meeting (PPUG).
Python's __div__ is similar to Mathematica's computer algebra notion of division in that you're free to divide any type by any type, providing this makes any algebraic sense, using a kind of liberal duck typing.
What I mean by that is __div__ by itself doesn't pre-specify anything, so if there's a meaningful way to deploy the division operator between arguments A, B, then go ahead and do it, write you code accordingly.
Or unmeaningful! Unlike (I presume) Mathematica, Python doesn't mind if you define a/b as multiplication. Your users might mind though. :-)
In Java, we could write __div__ in all different ways depending on valid type permutations (not that Java has operator overloading, just stricter typing at write time means you've gotta post "guards at the gate" in your methods). Python, with late binding, duck typing, won't post guards, but you'll still need to write algorithms capable of sorting out the possibilities. Maybe the user throws you a matrix? Has an inverse. OK, so __div__ makes some sense...
fractions.py in contrast, implements the narrow Q type, the rational number, defined as p / q where p, q are members of the set integers.
One could imagine a Fraction class that eats two complex numbers, or two Decimals. Computer algebra attaches meaning here, as in both sets we're able to define a multiplicative identity such that A / B means A * B**(-1) i.e. A * pow(B, -1) i.e. A * (1/B).
It's not so easy though. The specific purpose of the Fraction class is to always reduce the fraction to a canonical representation using the GCD algorithm (e.g. 15/12 becomes 5/4), which only applies to integers.
So the results of this operation, Fraction(A, B), might be some object holding the Decimal or Complex result. In generic algebra, everything's a duck, although conversion between types is possible (yes, that sounds nonsensical).
fractions.Fraction, on the other hand, barfs on anything but integers, isn't trying to be all divisions to all possible types, isn't pretending this is Mathematica or a generic CAS.
Fortunately Python supports a way of overloading binary operators where it is sufficient if *one* of the operands knows how to deal with the other. So Fraction(3, 4) * 2j happily returns 1.5j. You don't have to teach Fraction about Matrix if you can teach Matrix about Fraction.
Note that I'm not criticizing fractions.py in any way, am so far quite happy with it. I'm simply drawing attention to some fine points.
Related:
When I went to all the trouble to compose two functions, f and g, using __mul__, I'd get comments like: but the "open oh" (another symbol) is the "composition operator" i.e. "you're only using * because ASCII doesn't include the 'open oh'".
However, I was making a different point: that in group theory math texts, we're proud to use "regular" multiplication and division operators for such operations as "compositions of functions" because we're thinking __mul__ and __div__ have that generic meaning -- we neither need, nor want, the proliferation of symbols the "open oh" people think we must need.
There are different schools of thought about this actually. I don't think pride comes into it. Inventing and using specialized symbols is often useful in math because it provides more context. If you write "f * g" the reader would need to know in advance that f and g are functions or else they wouldn't know what was meant. But if you write "f o g" then the reader can *infer* that f and g are functions. Python happens to use the former (overloading based on argument types); Python's predecessor ABC used the latter (type inferencing based on operators). Neither is necessarily better than the other. There are also fields of mathematics where both are used, with a different meaning; e.g. f o g would mean functional composition while f * g could mean the function you get by multiplying f(x) and g(x). In Python: def open_oh(f, g): return lambda x: f(g(x)) def star(f, g): return lambda x: f(x) * g(x)
Note that by "open oh" I'm not talking about "big oh", a different notation that I don't think is redundant, agree with Knuth that if your calculus book doesn't include it, you're probably in one of those computer illiterate schools (ETS slave, whatever).
I think that comment is a little out of line. BTW big Oh is not part of calculus, it's part of complexity theory, a totally different field (more relevant to computers than calculus though). -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Wed, Dec 10, 2008 at 8:27 PM, Guido van Rossum <guido@python.org> wrote: << SNIP >>
There are different schools of thought about this actually. I don't think pride comes into it.
Well, *my* school is quite pompous about it. We think "open oh" is for sissies. But that's just us (quirky). Others more sobering. << GOOD STUFF >>
Note that by "open oh" I'm not talking about "big oh", a different notation that I don't think is redundant, agree with Knuth that if your calculus book doesn't include it, you're probably in one of those computer illiterate schools (ETS slave, whatever).
I think that comment is a little out of line. BTW big Oh is not part of calculus, it's part of complexity theory, a totally different field (more relevant to computers than calculus though).
Not part of calculus as commonly taught today, but *would* be if Donald Knuth had his way: http://micromath.wordpress.com/2008/04/14/donald-knuth-calculus-via-o-notati... Kirby
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
The problem is that calculus tends to deal with the concept of infinitesimally small and O(eps) is used for small eps. Computer Science tends to deal with complexity and O(n) is used for large n. The Big-Oh definitions are different: i) In calculus f(x) in O(g(x)) iff lim_{x\rightarrow 0} f(x)/g(x) < \infty ii) In CS f(x) in O(g(x)) iff lim_{x\rightarrow\infty} f(x)/g(x) < \infty It is common to use (i) to teach calculus (I was thought that way) but it is not common to use (ii) to teach algorithms. I do so in my notes for Design and Analysis of Algorithms [1] and students like it but many computer scientists believe that using limits is just an extra step. Massimo [1]http://bazaar.launchpad.net/%7Emdipierro/algorithms-animator/devel/download/... ________________________________________ From: edu-sig-bounces+mdipierro=cs.depaul.edu@python.org [edu-sig-bounces+mdipierro=cs.depaul.edu@python.org] On Behalf Of kirby urner [kirby.urner@gmail.com] Sent: Wednesday, December 10, 2008 10:39 PM To: edu-sig@python.org Subject: Re: [Edu-sig] computer algebra On Wed, Dec 10, 2008 at 8:27 PM, Guido van Rossum <guido@python.org> wrote: << SNIP >>
There are different schools of thought about this actually. I don't think pride comes into it.
Well, *my* school is quite pompous about it. We think "open oh" is for sissies. But that's just us (quirky). Others more sobering. << GOOD STUFF >>
Note that by "open oh" I'm not talking about "big oh", a different notation that I don't think is redundant, agree with Knuth that if your calculus book doesn't include it, you're probably in one of those computer illiterate schools (ETS slave, whatever).
I think that comment is a little out of line. BTW big Oh is not part of calculus, it's part of complexity theory, a totally different field (more relevant to computers than calculus though).
Not part of calculus as commonly taught today, but *would* be if Donald Knuth had his way: http://micromath.wordpress.com/2008/04/14/donald-knuth-calculus-via-o-notati... Kirby
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
You're lucky to understand this so well and to get (i) for calculus. I always thought big-O was used more to teach about algorithms (their efficiency), which is where I first encountered it. So maybe Knuth's calls for calculus reform were heeded after all and I'm just behind the times. On another topic: should we tell Channel 6 that Guido is right here on edu-sig. I think we should help hide him. I saw that documentary about Britney Spears yesterday. Paparazzi have made her life somewhat more difficult than it needs to be, even though she's a karate kid. http://www.channel6tvnews.com/story/agc2dHZuZXdzcgsLEgRjYXJkGPEkDA Kirby On Wed, Dec 10, 2008 at 10:04 PM, DiPierro, Massimo <MDiPierro@cs.depaul.edu> wrote:
The problem is that calculus tends to deal with the concept of infinitesimally small and O(eps) is used for small eps. Computer Science tends to deal with complexity and O(n) is used for large n. The Big-Oh definitions are different:
i) In calculus f(x) in O(g(x)) iff lim_{x\rightarrow 0} f(x)/g(x) < \infty
ii) In CS f(x) in O(g(x)) iff lim_{x\rightarrow\infty} f(x)/g(x) < \infty
It is common to use (i) to teach calculus (I was thought that way) but it is not common to use (ii) to teach algorithms. I do so in my notes for Design and Analysis of Algorithms [1] and students like it but many computer scientists believe that using limits is just an extra step.
Massimo
[1]http://bazaar.launchpad.net/%7Emdipierro/algorithms-animator/devel/download/...
________________________________________ From: edu-sig-bounces+mdipierro=cs.depaul.edu@python.org [edu-sig-bounces+mdipierro=cs.depaul.edu@python.org] On Behalf Of kirby urner [kirby.urner@gmail.com] Sent: Wednesday, December 10, 2008 10:39 PM To: edu-sig@python.org Subject: Re: [Edu-sig] computer algebra
On Wed, Dec 10, 2008 at 8:27 PM, Guido van Rossum <guido@python.org> wrote:
<< SNIP >>
There are different schools of thought about this actually. I don't think pride comes into it.
Well, *my* school is quite pompous about it. We think "open oh" is for sissies.
But that's just us (quirky). Others more sobering.
<< GOOD STUFF >>
Note that by "open oh" I'm not talking about "big oh", a different notation that I don't think is redundant, agree with Knuth that if your calculus book doesn't include it, you're probably in one of those computer illiterate schools (ETS slave, whatever).
I think that comment is a little out of line. BTW big Oh is not part of calculus, it's part of complexity theory, a totally different field (more relevant to computers than calculus though).
Not part of calculus as commonly taught today, but *would* be if Donald Knuth had his way:
http://micromath.wordpress.com/2008/04/14/donald-knuth-calculus-via-o-notati...
Kirby
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Hi All Just a general announcement: I've just updated my python programming book (Snake Wrangling for Kids) for Python 3. Not much in the way of changes really, adjusting print statements, use of range, etc. One of the advantages of being unpublished(/self-published), is that it's not as much of a big deal to update, when Guido changes the language... in fact... bring on Python 4000!!! ;-) The new PDFs are available here: http://www.briggs.net.nz/log/writing/snake-wrangling-for-kids/ Regards Jason
On Wed, Dec 10, 2008 at 8:27 PM, Guido van Rossum <guido@python.org> wrote: << SNIP >>
Fortunately Python supports a way of overloading binary operators where it is sufficient if *one* of the operands knows how to deal with the other. So Fraction(3, 4) * 2j happily returns 1.5j. You don't have to teach Fraction about Matrix if you can teach Matrix about Fraction.
This is one I keep coming back to. At the other end of the spectrum is thinking of * almost like an object and trying to write class methods using Mul as a platform. You have to check: is this a matrix by a vector? a Fraction by a floating point?... and so on through the myriad types allowed to multiply together (quite a long list). In contrast, with OO, numbers (those things which multiply) became more intelligent and swallowed their own methods, show up already fit to multiply, don't need "operators" floating out in space, match makers on steroids. 1 contains __mul__ inside of it, meets up with a complex, and... we get into left and right valency, i.e. operators have directionality. I think lots of experiments with this in the lab, and certainly fine to do those somewhat demented things like make __mul__ mere concatenation, otherwise oversimplify. This goes with my segment on "biotum", a sort of "hello world" from the OO world, where we make a Biotum class with primitive methods. The advent of 'Spore' has helped a lot I'd say. Kirby
On Wed, Dec 10, 2008 at 6:47 PM, kirby urner <kirby.urner@gmail.com> wrote: << SNIP >>
fractions.Fraction, on the other hand, barfs on anything but integers, isn't trying to be all divisions to all possible types, isn't pretending this is Mathematica or a generic CAS.
Note that I'm not criticizing fractions.py in any way, am so far quite happy with it. I'm simply drawing attention to some fine points.
OK, now I'm going to criticize a little. I think the more natural and useful choice would be to continue threads right here on edu-sig, regarding a Rational Number type, not just this Fraction type. The problem with Fraction is it's not actually much more than the notion of Ratio (how many times one fits in the other), whereas the Rational Number concept fits neatly in the sequence: N < W < Z < Q < R < C, where < could be replaced with the "subset" symbol. Those be Natural, Whole (Natural + 0), Integers, Rationals, Reals, and Complex respectively, except the Real type is quite problematic, is treated with Floats, Decimals and generators (iterable). The thing about Rationals is they're a field, closed under + and *, and therefore - and / (because of field properties). So a Rational is able to eat other Rationals for breakfast i.e. (1/3) / (3/1) makes plenty of sense, and all integers are really just rationals in disguise i.e. 0 = 0/1, 1 = 1/1 etc. If Fraction could eat Fraction type objects, then we could have continued fractions more easily, have other fun. The silver lining here is fractions.py was actual named that, and not rationals.py, which means we still have a hole to fill, a more generic class, yet not too generic, not open to complex or matrix arguments, just to rationals, integers a subtype. Kirby
But fractions *can* eat fractions. Instead of Fraction(f1, f2) you just write f1/f2. In general you should just stick to the latter, and leave the Fraction() constructor for when the / operator would pick a different type (as in 1/2, which becomes a float). You can also write it as Fraction(1) / Fraction(2). --Guido van Rossum (home page: http://www.python.org/~guido/) On Sun, Dec 14, 2008 at 3:05 PM, kirby urner <kirby.urner@gmail.com> wrote:
On Wed, Dec 10, 2008 at 6:47 PM, kirby urner <kirby.urner@gmail.com> wrote:
<< SNIP >>
fractions.Fraction, on the other hand, barfs on anything but integers, isn't trying to be all divisions to all possible types, isn't pretending this is Mathematica or a generic CAS.
Note that I'm not criticizing fractions.py in any way, am so far quite happy with it. I'm simply drawing attention to some fine points.
OK, now I'm going to criticize a little.
I think the more natural and useful choice would be to continue threads right here on edu-sig, regarding a Rational Number type, not just this Fraction type.
The problem with Fraction is it's not actually much more than the notion of Ratio (how many times one fits in the other), whereas the Rational Number concept fits neatly in the sequence: N < W < Z < Q < R < C, where < could be replaced with the "subset" symbol. Those be Natural, Whole (Natural + 0), Integers, Rationals, Reals, and Complex respectively, except the Real type is quite problematic, is treated with Floats, Decimals and generators (iterable).
The thing about Rationals is they're a field, closed under + and *, and therefore - and / (because of field properties). So a Rational is able to eat other Rationals for breakfast i.e. (1/3) / (3/1) makes plenty of sense, and all integers are really just rationals in disguise i.e. 0 = 0/1, 1 = 1/1 etc.
If Fraction could eat Fraction type objects, then we could have continued fractions more easily, have other fun.
The silver lining here is fractions.py was actual named that, and not rationals.py, which means we still have a hole to fill, a more generic class, yet not too generic, not open to complex or matrix arguments, just to rationals, integers a subtype.
Kirby _______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Ah so... My focus on the constructor as a way to trigger the initial division (complete with gcd), was blinding me to the role of the __div__ operator in gluing the things together. I need to get back to those continued fraction studies then, using my new understanding. Thank you for opening my eyes Guido. Kirby On Sun, Dec 14, 2008 at 3:39 PM, Guido van Rossum <guido@python.org> wrote:
But fractions *can* eat fractions. Instead of Fraction(f1, f2) you just write f1/f2. In general you should just stick to the latter, and leave the Fraction() constructor for when the / operator would pick a different type (as in 1/2, which becomes a float). You can also write it as Fraction(1) / Fraction(2).
--Guido van Rossum (home page: http://www.python.org/~guido/)
participants (4)
-
DiPierro, Massimo -
Guido van Rossum -
Jason Briggs -
kirby urner