From: <bc...@wo...> - 2001-01-25 20:07:07
|
Hi, I have been working on a change to the coercion model that matches the change that CPython 2.1 have introduced. The change only affect the implementation of PyObject and its subclasses. It have no effect on python objects that define __coerce__ or any of the other __XXX__ number methods. The effect of the change is that the __XXX__ number methods can receive argument(s) that aren't of the same type as itself. It is then the (new) responsibility of each __XXX__ method to check its argument and return Py.NotImplemented if the operation cannot be done with such an argument. As a result the __coerce_ex__ is no longer called. The patch, as I have it now, does not supply a backward compatiblity mode and that is subject on which I'm seeking feedback: I would like to hear from you if you have coded your own PyObject subclass which override any of the number methods. Take a look at the "new" way that this can be coded (example below is taken from PyFloat) and send me your feedback and comments. Adding backward compatibility is ofcourse possible, but it would mean we have to carry around some kind of flag around (NEW_STYLE_NUMBER) and I would rather avoid that if possible. I would also like to get rid of the currect coercion code because it complicated and there are bugs in it. The benefit of the new coercion model is improved speed when mixing object types in operations because it isn't necessary to create a temporary object and improved control from an extension type because it now gets the unmodified arguments pass to it. The full patch can be found here: http://sourceforge.net/patch/index.php?func=detailpatch&patch_id=103419&group_id=12867 A few example methods taken from PyFloat. It showns how the numeric methods can be implemented under the new coercion mode: public PyObject __add__(PyObject right) { if (!canCoerce(right)) return Py.NotImplemented; double rightv = coerce(right); return new PyFloat(value + rightv); } public PyObject __radd__(PyObject left) { return __add__(left); } public PyObject __sub__(PyObject right) { if (!canCoerce(right)) return Py.NotImplemented; double rightv = coerce(right); return new PyFloat(value - rightv); } public PyObject __rsub__(PyObject left) { if (!canCoerce(left)) return Py.NotImplemented; double leftv = coerce(left); return new PyFloat(leftv - value); } private static final boolean canCoerce(PyObject other) { return other instanceof PyFloat || other instanceof PyInteger || other instanceof PyLong; } private static final double coerce(PyObject other) { if (other instanceof PyFloat) return ((PyFloat) other).value; else if (other instanceof PyInteger) return ((PyInteger) other).getValue(); else if (other instanceof PyLong) return ((PyLong) other).doubleValue(); else throw Py.TypeError("xxx"); } regards, finn |