__coerce__ vs. new-style classes

Hallvard B Furuseth h.b.furuseth at usit.uio.no
Mon Aug 2 21:10:00 CEST 2004


John Roth wrote:
>"Hallvard B Furuseth" <h.b.furuseth at usit.uio.no> wrote in message
>news:HBF.20040802t150 at bombur.uio.no...
>> Why do new-style classes disable __coerce__()?
>> It seems cumbersome to have to write a whole set of methods (e.g.
>> __add__, __radd__, etc.) to get the same effect.  Is there some way to
>> automatically generate those methods, or are we simply not supposed to
>> do coercion for some reason?
> 
> I'm mildly confused by your example. __coerce__()
> converts the arguements to a common type, and then
> presumably requests that type to do the operation. That
> type might not be one of the two original types!
> 
> It's not the same thing as the __op__, __rop__
> pair. That simply allows the right object to do the
> operation if the left object can't.

Yes:

>>> class DeferredIntType:
...     def __init__(self, fetch, *args, **kwargs):
...         def _fetch():
...             v = long(fetch(*args, **kwargs))
...             self.value = lambda: v
...             return v
...         self.value = _fetch
...     def __long__(self):         return self.value()
...     def __int__(self):          return int(self.value())
...     def __str__(self):          return str(self.value())
...     def __coerce__(self, other):
...         if isinstance(other, (int, long)):
...             return type(other)(self.value()), other
... 
>>> DeferredIntType(len, 'foobar') + 3
9

Can't add two of them without __add__ & co, but can do just about
everything else just by writing four small methods.

If I do include __add__ & co, they won't all have to coerce the
arguments 'by hand', or worry about what to do if they don't know
how to add the type of argument they received.

Without __coerce__, what should __add__(self, other) do if it doesn't
know how to add the arguments, but the other argument might know how?
It can't just call other.__radd__(self): That might give up and call
__add__ again.
In some cases it might help to call coerce() by hand, but I note the
ref manual says 'In Python 3.0, coercion will not be supported.'.

> The notion of type coercion makes a great deal of sense
> in languages such as C, where you have 8 integer types
> and 3 float types, but abstracting it out as a separate
> operation makes very little sense in Python, where you
> have 3 numeric types (int, long and float) and two string
> types (normal and unicode). The overhead of doing
> coercion as a separate operation simply doesn't make
> a lot of sense.

Well, I was thinking of types like the above, which emulate
numeric types.  The case which got me started was one which
emulates the DECIMAL (or NUMERIC) SQL type in PgSQL.py.

> At least, that's the way I understand it. Section 3.3.8
> (Coercion Rules) of the 2.3 Language Reference gives
> the official reasons for moving away from doing coercion
> as part of operations. It simply got to complex to
> document properly.

I noticed that; I hadn't realized it was the argument for disabling
coercion completey.

-- 
Hallvard



More information about the Python-list mailing list