On Saturday, March 13, 2010 9:03:36 AM UTC-8, Jonathan Lundell wrote: > I've got a subclass of fractions.Fraction called Value; it's a mostly > trivial class, except that it overrides __eq__ to mean 'nearly equal'. > However, since Fraction's operations result in a Fraction, not a > Value, I end up with stuff like this: > > x = Value(1) + Value(2) > > where x is now a Fraction, not a Value, and x == y uses > Fraction.__eq__ rather than Value.__eq__. > > This appears to be standard Python behavior (int does the same thing). > I've worked around it by overriding __add__, etc, with functions that > invoke Fraction but coerce the result. But that's tedious; there are a > lot of methods to override. > > So I'm wondering: is there a more efficient way to accomplish what I'm > after?
I recently implemented a different approach to this. I've got: class Rational(fractions.Fraction): ... and some methods of my own, including my own __new__ and __str__ (which is one of the reasons I need the class). Then after (outside) the class definition, this code that was inspired by something similar I noticed in Python Cookbook. There are two things going on here. One is, of course, the automation at import time. The other is that the wrapper gets a Fraction instance and simply overrides __class__, rather than creating yet another Rational and unbinding the interim Fraction. Seems to work quite well. # create wrappers for Rational methods that return Rational (not Fraction) objects # def _wrap_method(method): "wrap a Fraction method in Rational" fraction_method = getattr(Fraction, method) def x(*args): "call Fraction and change result to Rational" v = fraction_method(*args) v.__class__ = Rational return v x.func_name = method setattr(Rational, method, x) for name in "pos neg abs trunc".split(): _wrap_method("__%s__" % name) # wrap method, eg __pos__ for name in "add sub mul div truediv floordiv mod pow".split(): _wrap_method("__%s__" % name) # wrap method, eg __add__ _wrap_method("__r%s__" % name) # wrap reversed-argument method, eg __radd__ del _wrap_method -- http://mail.python.org/mailman/listinfo/python-list