On Wed, Nov 9, 2011 at 3:02 PM, Steven D'Aprano
Case Van Horsen wrote:
Currently the functions round(), math.ceil(), math.floor(), and math.trunc() all check for the existence of a special method (__round__, __ceil__, __floor__, and __trunc__). Would it be possible to enhance the math and cmath modules to check for the existence of a special method for (almost) functions? For example, math.sin(obj) would first check for obj.__sin__.
I would not object to this.
The only function I can honestly say I have had a concrete use-case for is math.sqrt. This comes up from time to time, e.g.:
http://bytes.com/topic/python/answers/463861-how-overload-sqrt-module http://permalink.gmane.org/gmane.comp.python.general/694849
However, how far should we go? Does every function in the math module require a dunder method, e.g. __degrees__ ? What happens if we add more functions, say math.bessel? Do we really expect that all numeric types must support a __bessel__ method? I suspect that this proposal is actually bigger than it seems at first glance.
It would be completely optional for a numeric type to support these methods. If they're not supported, the numeric type is converted to a float and then math.function proceeds as it currently does.
We can:
* Do nothing (the status quo). If you write a numeric type, you can support a small number of mathematical operations, such as + and math.floor, but not others, such as math.sqrt or math.sin.
* Officially recommend that people monkey-patch the math module if they want to write a drop-in replacement for numeric types. I consider this unspeakable, but mention it for completeness since others have raised the possibility.
* Add support for dunder methods in an ad hoc manner, when and as requested, without making any promises about any other functions.
I hacked mathmodule.c FUNC1 macro to perform the lookup the many of math module functions. It was only about 15 lines of code (but it doesn't check if NotImplemented is returned.) Unfortunately, it increases the running time of math.sin, for example, by 15%. I need to look at the Identifier API to see if that helps the performance but I don't think 15% is a penalty everyone should pay.
* Add support for dunder methods in a systematic way. This would require distinguishing between fundamental operations that should support dunder methods, and those that shouldn't (if any). This will probably need a PEP.
Especially true if new nb_slots need to be created to avoid the performance impact. I was hoping the performance impact of the special method lookup was negligible so it could be a low impact change.
* Instead of having to decide what operations should be supported ahead of time, perhaps there is a way for types to register themselves with the math module, e.g. say "I support sin, but not sinh". Somewhat akin to the way ABCs work, at least conceptually. One advantage of that may be that numeric classes won't have to use dunder methods for supporting the math module, e.g. MyNumber might register sin rather than __sin__.
As long as they support __float__, they'll continue to work with the math module.
-- Steven
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas