class inheritance
JLundell
jlundell at pobox.com
Fri Dec 17 17:19:54 EST 2010
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
More information about the Python-list
mailing list