-----Original Message-----
From: Chris Angelico <ros...@gmail.com>
Sent: 05 March 2020 11:42
To: python-ideas@python.org
Subject: [Python-ideas] Re: IDEA: Allow override of all assignments of a built
in type to be a different type
On Thu, Mar 5, 2020 at 8:27 PM Steve Barnes <gadgetst...@live.co.uk> wrote:
>
> One of the lovely things about Python is that we have the capability to avoid
> issues such as the vagaries of the floating point type with libraries such as
> decimal and fractions. This is wonderous to me but comes with an issue that I
> suspect is limiting its usage. That issue is that you have to litter your
> code with constructors of those types, e.g.
>
> from decimal import * # I know why this is bad but it comes straight
> from the examples a = Decimal("0.1") # Needs to be a string to avoid
> being temporarily a float b = Decimal("0.2") # Ditto c =
> Decimal("0.3") # Ditto
>
> a + b == c # Magic this works!
As an aside, this complaint comes up in basically every language, and it's a
consequence of the literal 0.1 not actually meaning one tenth.
Nobody would bat an eyelid if you show that, say:
x = 0.3333333 # one third
y = 0.6666666 # two thirds
x + y != 1.0
because they've obviously been rounded (those are NOT complete representations
of those fractions). It's only with fifths and tenths that people are
surprised, and only because they don't understand that computers work in binary
:)
That said, though, there are a number of good reasons for wanting to change the
interpretation of literals. But by the time you get to executing the module
code, it's too late - the literals get parsed and compiled into the code
object, and they're already the values they are going to ultimately be.
There are two approaches that would reasonably plausibly work for this. It's
possible to redefine literal parsing using a future directive ("from __future__
import unicode_literals"), but those have to be defined entirely by the
language. To do it in custom code, you'd need instead to run some code before
your module is parsed - for example, an import hook.
This would have to NOT be done by default - you'd have to do it on a per-module
basis - because any change like this would break a lot of things. (Even if you
keep it just to your module, using Decimal can create bizarre situations - such
as where the average of two numbers is not between them.) Ultimately, I think
the best solution in current Python is to just import Decimal as D and then use
the shorter name.
Hmm, is there a PEP regarding Decimal literals? I couldn't find one, although
there is PEP 240 regarding rational literals. Maybe it's time to write up a
rejected PEP explaining exactly what the problems are with Decimal literals.
From memory, the problems are (a) it'd effectively require the gigantic decimal
module to be imported by default, and (b) contexts don't work with literals.
But since Decimal literals are such an obvious solution to most of the above
problems, I think it'd be good to have a document saying why it won't help.
ChrisA
[Steve Barnes]
I think that a part of the problem is that because Decimal silently accepts
both float and string literal inputs things get surprising e.g.:
In [5]: D(0.3) == D('0.3')
Out[5]: False
In [6]: D(0.5) == D('0.5')
Out[6]: True
In [7]: D(0.1) * 10 == 1
Out[7]: False
In [8]: D(0.5) * 2 == 1
Out[8]: True
Maybe a way forwards, (if we have no widely applicable way of preventing the
actual call to the initialiser being interpreted as a float before it is seen),
would be to:
1. Deprecate the use of the Decimal initialiser with float inputs so that
decimal.Decimal(0.1), etc., issues a warning
2. Possibly have a from __future__ import NoDecimalFloat or similar
3. Eventually outlaw float as an input to the initialiser.
While this would "break" code which happen to work as expected, e.g.
decimal.Decimal(0.5) but at least we would have consistent behaviour and fail
early rather than potentially working but giving incorrect or inconsistent
results.
While a rejected PEP would give somewhere to point to for explanations I am
afraid that all to many python users never read any of the PEPs or only PEP8.
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/python-ideas@python.org/message/L7JZRRP7K6VKKXD3YNOEZYF4FEO5CIXU/
Code of Conduct: http://python.org/psf/codeofconduct/