On Wed, 9 Nov 2011 16:55:16 -0800 Case Van Horsen firstname.lastname@example.org wrote:
On Wed, Nov 9, 2011 at 3:02 PM, Steven D'Aprano email@example.com wrote:
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.:
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.
- 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.
You can special-case floats using PyFloat_CheckExact and see if that helps.