New submission from Mark Dickinson <dicki...@gmail.com>:

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.

----------
messages: 370181
nosy: mark.dickinson, serhiy.storchaka
priority: normal
severity: normal
status: open
title: Expose PyFloat_ToDouble at Python level: operator.to_float?
type: enhancement
versions: Python 3.10

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue40801>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to