Coerce that can pay attention to type of operation

jepler epler jepler.lnk at lnk.ispi.net
Sun Oct 1 14:01:44 EDT 2000


I'm writing a rational number class, as an exercise.  As I implemented
+, -, *, /, I realized that I could use __coerce__ to turn integers
and longs into Ratios, and when the "other" arg was an unrecognized type,
to convert the Ratio into a real.

However, for __pow__, I wish that I could follow another rule, where:
	r = Ratio()
	f = 1.0
	i = 1

	r**f -> float(r) ** f
	r**i -> Ratio(r.num ** i, r.den ** i)
	f**r -> f ** float(r)
	i**r -> i ** float(r)

However, this means that __coerce__ needs to know what operation is
about to be performed.  Obviously, you can't do this without an extension
to python.

I could choose to put the __coerce__-like code into each method, but
increased code size is just what __coerce__ is supposed to avoid.

Thus, I wonder whether a method which is told the upcoming operation,
perhaps named __coerce3__ (because it would take three arguments)
could solve this problem:

class Ratio:
	def __mul__(self, other):
		assert isinstance(Ratio, other)
		return Ratio(self.num * other.num, self.den * other.den)

	def __pow__(self, other):
		assert type(other) in (IntType, LongType)
		return Ratio(self.num ** other, self.den ** other)

	def __coerce3__(self, other, op):
		if op == "__pow__":
			if type(other) in (IntType, LongType):
				return (self, other)
		elif op != "__rpow__":
			if type(other) in (IntType, LongType):
				return self, Ratio(other)
			elif isinstance(Ratio, other):
				return self, other
		return float(self), other)

I don't have a patch, but it looks like one could be developed
fairly simply in Objects/classobject.c:halfbinop().  Changes to let
coerce(a, b, operation type) call __coerce3__ would take a little
more work.

Am I missing a better way to do what I want?  If not, is there any
merit to the idea of __coerce3__?

Jeff



More information about the Python-list mailing list