This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author mark.dickinson
Recipients mark.dickinson, serhiy.storchaka
Date 2020-05-28.09:23:05
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1590657786.78.0.118668826809.issue40801@roundup.psfhosted.org>
In-reply-to
Content
Motivation
----------

Various pieces of Python need to do a duck-typed conversion of an arbitrary float-like object to a float (or a C double) for computation. The math module is the most obvious example - most math-module functions that accept a float also accept float-like things, like np.float32 and Decimal - but it's not the only place that this is needed.

This conversion is easy at C level, being encapsulated in a single function call: PyFloat_AsDouble. (Plus a PyFloat_FromDouble if you want to go back to Python space, of course.)

But: it's surprisingly awkward to get an equivalent effect in pure Python code. Options are:

1. Do an explicit type check to exclude str, bytes and bytearray, and then call the float constructor. But the extra type check is ugly and potentially not future-proof.

2. Call type(obj).__float__(obj). But this has several problems: __float__ can return an instance of a float subclass rather than a strict float, and then it's hard to convert to an actual float. And in more recent versions of Python, this no longer matches PyFloat_AsDouble because it doesn't account for objects that provide __index__ but not __float__. And calling dunder methods directly should rarely be the Right Way To Do It.

3. Use the implicit ability of the math module to do this, for example using math.copysign(obj, obj). This works! But it's not a clear expression of the intent.

This has bitten me in Real Code (TM), where I've needed a way to convert an arbitrary float-like thing to a float, ideally following the same rules that Python uses. And also ideally in such a way that my own code doesn't have to change if Python updates its rules, as for example it did recently to allow things with an __index__ to be considered float-like.


Proposal
--------

Add a new operator function "operator.as_float" which matches Python's duck-typed acceptance of float-like things, in the same way that the existing operator.index matches Python's implicit acceptance of int-like things in various APIs that expect integers.

Internally, "operator.as_float" would simply call PyFloat_AsDouble followed by PyFloat_FromDouble (possibly with a fast path to pass objects of exact type float through directly).



Related: #17576.
History
Date User Action Args
2020-05-28 09:23:06mark.dickinsonsetrecipients: + mark.dickinson, serhiy.storchaka
2020-05-28 09:23:06mark.dickinsonsetmessageid: <1590657786.78.0.118668826809.issue40801@roundup.psfhosted.org>
2020-05-28 09:23:06mark.dickinsonlinkissue40801 messages
2020-05-28 09:23:05mark.dickinsoncreate