[Python-ideas] Deprecate the round builtin

99 views
Skip to first unread message

Mike Graham

unread,
Sep 26, 2012, 2:51:22 PM9/26/12
to python-ideas
The builtin round function is completely useless. I've never seen
anyone use it constructively. Usually people using it are new
programmers who are not comfortable with or aware of string
formatting. Sometimes people use it to poorly replicate functionality
that's implemented correctly in the decimal module.

Mike
_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas

Guido van Rossum

unread,
Sep 26, 2012, 2:55:10 PM9/26/12
to mikeg...@gmail.com, python-ideas
On Wed, Sep 26, 2012 at 11:51 AM, Mike Graham <mikeg...@gmail.com> wrote:
> The builtin round function is completely useless. I've never seen
> anyone use it constructively. Usually people using it are new
> programmers who are not comfortable with or aware of string
> formatting. Sometimes people use it to poorly replicate functionality
> that's implemented correctly in the decimal module.

You're probably right. It has ancient ancestry: it was one of the
functions I copied directly from ABC. (It's actually more useful now
that floats are printed with minimal digits.)

But given the pain of removing a builtin, is it worth it? maybe we can
just document the better ways of accomplishing its tasks?

--
--Guido van Rossum (python.org/~guido)

Mark Dickinson

unread,
Sep 26, 2012, 3:22:19 PM9/26/12
to mikeg...@gmail.com, python-ideas
On Wed, Sep 26, 2012 at 7:51 PM, Mike Graham <mikeg...@gmail.com> wrote:
> The builtin round function is completely useless. I've never seen
> anyone use it constructively

I disagree that it's *completely* useless: the one-argument form
(take a float, return the closest integer) is a fundamental and useful
mathematics operation, just like floor and ceiling. It would be crazy
to get rid of that. I could live with it moving from builtins into
the math module, though.

Agreed that the two-argument form causes a lot of confusion, though.

--
Mark

M.-A. Lemburg

unread,
Sep 26, 2012, 3:36:54 PM9/26/12
to Mark Dickinson, python-ideas
Mark Dickinson wrote:
> On Wed, Sep 26, 2012 at 7:51 PM, Mike Graham <mikeg...@gmail.com> wrote:
>> The builtin round function is completely useless. I've never seen
>> anyone use it constructively
>
> I disagree that it's *completely* useless: the one-argument form
> (take a float, return the closest integer) is a fundamental and useful
> mathematics operation, just like floor and ceiling. It would be crazy
> to get rid of that. I could live with it moving from builtins into
> the math module, though.
>
> Agreed that the two-argument form causes a lot of confusion, though.

It's actually quite common in finance and time calculations to
round to the nearest say basis point, cent or say micro second
in calculations (rather than just string formatting). round()
is perfect for that and easy to use.

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source (#1, Sep 26 2012)
>>> Python/Zope Consulting and Support ... http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
________________________________________________________________________
2012-10-29: PyCon DE 2012, Leipzig, Germany ... 33 days to go
2012-10-23: Python Meeting Duesseldorf ... 27 days to go
2012-09-26: Released mxODBC.Connect 2.0.1 ... http://egenix.com/go34
2012-09-25: Released mxODBC 3.2.1 ... http://egenix.com/go33


eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
Registered at Amtsgericht Duesseldorf: HRB 46611
http://www.egenix.com/company/contact/

Joshua Landau

unread,
Sep 26, 2012, 3:47:09 PM9/26/12
to M.-A. Lemburg, python-ideas
On 26 September 2012 20:36, M.-A. Lemburg <m...@egenix.com> wrote:
Mark Dickinson wrote:
> On Wed, Sep 26, 2012 at 7:51 PM, Mike Graham <mikeg...@gmail.com> wrote:
>> The builtin round function is completely useless. I've never seen
>> anyone use it constructively
>
> I disagree that it's *completely* useless:  the one-argument form
> (take a float, return the closest integer) is a fundamental and useful
> mathematics operation, just like floor and ceiling.  It would be crazy
> to get rid of that.  I could live with it moving from builtins into
> the math module, though.
>
> Agreed that the two-argument form causes a lot of confusion, though.

It's actually quite common in finance and time calculations to
round to the nearest say basis point, cent or say micro second
in calculations (rather than just string formatting). round()
is perfect for that and easy to use.

Agreed. I've rounded before. It's useful.

Maybe not as useful as all() or whatever, but I don't see how it's "redundant". 

Mark Dickinson

unread,
Sep 26, 2012, 4:02:39 PM9/26/12
to M.-A. Lemburg, python-ideas
On Wed, Sep 26, 2012 at 8:36 PM, M.-A. Lemburg <m...@egenix.com> wrote:
> It's actually quite common in finance and time calculations to
> round to the nearest say basis point, cent or say micro second
> in calculations

That's exactly where the problems creep in, though. Naive users
expect rounding to give 'correct' results for decimal halfway cases,
and then are surprised when it doesn't.

>>> round(2.675, 2)
2.67

So you end up explaining again and again that computing binary
approximations to decimal rounds of binary approximations of decimal
halfway cases is a bad idea.

Mark

M.-A. Lemburg

unread,
Sep 26, 2012, 4:17:36 PM9/26/12
to Mark Dickinson, python-ideas
Mark Dickinson wrote:
> On Wed, Sep 26, 2012 at 8:36 PM, M.-A. Lemburg <m...@egenix.com> wrote:
>> It's actually quite common in finance and time calculations to
>> round to the nearest say basis point, cent or say micro second
>> in calculations
>
> That's exactly where the problems creep in, though. Naive users
> expect rounding to give 'correct' results for decimal halfway cases,
> and then are surprised when it doesn't.
>
>>>> round(2.675, 2)
> 2.67
>
> So you end up explaining again and again that computing binary
> approximations to decimal rounds of binary approximations of decimal
> halfway cases is a bad idea.

But that's the fault of round(), is it ? ;-) It's more one of
educating people of what to expect when working with floats.

Your example is a typical case that comes up when people enter
examples and wonder why they don't see the expected results.

In calculations, statistics, numeric, etc. such corner cases are
not all that common, so things are not as bad as they may appear
on first sight.

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Source (#1, Sep 26 2012)
>>> Python/Zope Consulting and Support ... http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
________________________________________________________________________
2012-10-29: PyCon DE 2012, Leipzig, Germany ... 33 days to go
2012-10-23: Python Meeting Duesseldorf ... 27 days to go
2012-09-26: Released mxODBC.Connect 2.0.1 ... http://egenix.com/go34
2012-09-25: Released mxODBC 3.2.1 ... http://egenix.com/go33


eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
Registered at Amtsgericht Duesseldorf: HRB 46611
http://www.egenix.com/company/contact/

Mike Graham

unread,
Sep 26, 2012, 4:36:28 PM9/26/12
to Python-Ideas
On Wed, Sep 26, 2012 at 3:36 PM, M.-A. Lemburg <m...@egenix.com> wrote:
> It's actually quite common in finance and time calculations to
> round to the nearest say basis point, cent or say micro second
> in calculations (rather than just string formatting). round()
> is perfect for that and easy to use.

Rounding to the nearest cent is an important operation, but it's not
one that round really handles well. It certainly can't always round
you exactly to the nearest hundredth--it can round you there with some
inaccuracy when you're doing it to have an exact number. We have the
decimal module (or sometimes just plain int) to handle this in a much
more robust, correct way.

I'm not personally familiar with the cases where one would want to
round time like that for computations, but I can't help but suspect
that if you want a quantity in a number of microseconds, you'd be
wanting it to be exact as well.

round only appears to be useful. Using it to try to get something "in
cents" or similar is a strong code smell and probably a bug.

Mike

Joao S. O. Bueno

unread,
Sep 26, 2012, 5:00:24 PM9/26/12
to Python-Ideas
> On Wed, Sep 26, 2012 at 3:36 PM, M.-A. Lemburg <m...@egenix.com> wrote:
>> It's actually quite common in finance and time calculations to
>> round to the nearest say basis point, cent or say micro second
>> in calculations (rather than just string formatting). round()
>> is perfect for that and easy to use.
>

On the other hand, having round with a second parameter to return a Decimal
would be quite usefull. I can't see a way of changing the type returned
by the built-in round without crashing half the World --- but maybe it would
be possible to deprecate only the two-parameter form of the built-in round,
and add a decimal.round Decimal factory?

js
-><-

Mark Adam

unread,
Sep 26, 2012, 5:15:52 PM9/26/12
to Joao S. O. Bueno, Python-Ideas
> On the other hand, having round with a second parameter to return a Decimal
> would be quite usefull. I can't see a way of changing the type returned
> by the built-in round without crashing half the World --- but maybe it would
> be possible to deprecate only the two-parameter form of the built-in round,
> and add a decimal.round Decimal factory?

On second thought, the idea of "namespaces" within the interpreter
(like Tim Peters was suggesting I think in the doctest module) could
put some order to built-ins and globals within the interpreter.
round(), hex() and others could be in the namespace "Numbers" (Named
by their associated type), similarly for the other type-specific
builtins.

Create a keyword "expose" to dump a particular namespace into the
global scope when you don't want to type "Numbers.round(f)".

Thoughts?

markj

Oleg Broytman

unread,
Sep 26, 2012, 5:21:27 PM9/26/12
to python...@python.org
On Wed, Sep 26, 2012 at 04:15:52PM -0500, Mark Adam <dreamin...@gmail.com> wrote:
> On second thought, the idea of "namespaces" within the interpreter
> (like Tim Peters was suggesting I think in the doctest module) could
> put some order to built-ins and globals within the interpreter.
> round(), hex() and others could be in the namespace "Numbers" (Named
> by their associated type), similarly for the other type-specific
> builtins.
>
> Create a keyword "expose" to dump a particular namespace into the
> global scope when you don't want to type "Numbers.round(f)".

What is the difference between such namespaces and modules (which
*are* namespaces)?

Oleg.
--
Oleg Broytman http://phdru.name/ p...@phdru.name
Programmers don't die, they just GOSUB without RETURN.

Daniel Holth

unread,
Sep 26, 2012, 5:21:40 PM9/26/12
to Mark Adam, python-ideas

Normally deprecation means you keep it forever but don't mention it much in the docs...

Greg Ewing

unread,
Sep 26, 2012, 5:29:20 PM9/26/12
to python-ideas
M.-A. Lemburg wrote:
> In calculations, statistics, numeric, etc. such corner cases are
> not all that common, so things are not as bad as they may appear
> on first sight.

If the corner cases don't matter, I'd say you don't
need to round your internal representations in the
first place. Rounding on output is sufficient and
probably preferable.

If they *do* matter -- such as when cents need to
add up exactly -- you're much better off using
Decimals. Two-argument round() is an attractive
nuisance in that case, IMO.

--
Greg

Mark Adam

unread,
Sep 26, 2012, 5:30:33 PM9/26/12
to python...@python.org
On Wed, Sep 26, 2012 at 4:21 PM, Oleg Broytman <p...@phdru.name> wrote:
> On Wed, Sep 26, 2012 at 04:15:52PM -0500, Mark Adam <dreamin...@gmail.com> wrote:
>> On second thought, the idea of "namespaces" within the interpreter
>> (like Tim Peters was suggesting I think in the doctest module) could
>> put some order to built-ins and globals within the interpreter.
>> round(), hex() and others could be in the namespace "Numbers" (Named
>> by their associated type), similarly for the other type-specific
>> builtins.
>>
>> Create a keyword "expose" to dump a particular namespace into the
>> global scope when you don't want to type "Numbers.round(f)".
>
> What is the difference between such namespaces and modules (which
> *are* namespaces)?

Modules reside on file and are changeable, Namespaces solely in
memory, defined by the Interpreter itself.

mark

Amaury Forgeot d'Arc

unread,
Sep 26, 2012, 5:32:52 PM9/26/12
to M.-A. Lemburg, python-ideas
2012/9/26 M.-A. Lemburg <m...@egenix.com>:
>>>>> round(2.675, 2)
>> 2.67
>>
>> So you end up explaining again and again that computing binary
>> approximations to decimal rounds of binary approximations of decimal
>> halfway cases is a bad idea.
>
> But that's the fault of round(), is it ? ;-) It's more one of
> educating people of what to expect when working with floats.

Could we change the round() behavior?
The second parameter is the number of decimal places,
so the operation could be defined in terms of decimal digits.

A similar change was already done for float.__str__.

--
Amaury Forgeot d'Arc

Oleg Broytman

unread,
Sep 26, 2012, 5:51:30 PM9/26/12
to python...@python.org
On Wed, Sep 26, 2012 at 04:30:33PM -0500, Mark Adam <dreamin...@gmail.com> wrote:
> On Wed, Sep 26, 2012 at 4:21 PM, Oleg Broytman <p...@phdru.name> wrote:
> > On Wed, Sep 26, 2012 at 04:15:52PM -0500, Mark Adam <dreamin...@gmail.com> wrote:
> >> On second thought, the idea of "namespaces" within the interpreter
> >> (like Tim Peters was suggesting I think in the doctest module) could
> >> put some order to built-ins and globals within the interpreter.
> >> round(), hex() and others could be in the namespace "Numbers" (Named
> >> by their associated type), similarly for the other type-specific
> >> builtins.
> >>
> >> Create a keyword "expose" to dump a particular namespace into the
> >> global scope when you don't want to type "Numbers.round(f)".
> >
> > What is the difference between such namespaces and modules (which
> > *are* namespaces)?
>
> Modules reside on file and are changeable,

Oh, really? What is the file for module sys? thread? zipimport?

> Namespaces solely in
> memory, defined by the Interpreter itself.

Oleg.
--
Oleg Broytman http://phdru.name/ p...@phdru.name
Programmers don't die, they just GOSUB without RETURN.

MRAB

unread,
Sep 26, 2012, 6:07:01 PM9/26/12
to python-ideas
On 2012-09-26 21:17, M.-A. Lemburg wrote:
> Mark Dickinson wrote:
>> On Wed, Sep 26, 2012 at 8:36 PM, M.-A. Lemburg <m...@egenix.com> wrote:
>>> It's actually quite common in finance and time calculations to
>>> round to the nearest say basis point, cent or say micro second
>>> in calculations
>>
>> That's exactly where the problems creep in, though. Naive users
>> expect rounding to give 'correct' results for decimal halfway cases,
>> and then are surprised when it doesn't.
>>
>>>>> round(2.675, 2)
>> 2.67
>>
>> So you end up explaining again and again that computing binary
>> approximations to decimal rounds of binary approximations of decimal
>> halfway cases is a bad idea.
>
> But that's the fault of round(), is it ? ;-) It's more one of
> educating people of what to expect when working with floats.
>
> Your example is a typical case that comes up when people enter
> examples and wonder why they don't see the expected results.
>
> In calculations, statistics, numeric, etc. such corner cases are
> not all that common, so things are not as bad as they may appear
> on first sight.
>
If we're going to move 'round' into 'math' because it sometimes gives
results which puzzle naive users, shouldn't we do the same to 'float'?
:-)

Alexander Belopolsky

unread,
Sep 26, 2012, 6:14:34 PM9/26/12
to python-ideas, python-ideas




On Sep 26, 2012, at 6:07 PM, MRAB <pyt...@mrabarnett.plus.com> wrote:

> If we're going to move 'round' into 'math' because it sometimes gives
> results which puzzle naive users, shouldn't we do the same to 'float'?
> :-)

+1

In Python 4, type(1.5) should be Decimal, not float.

Steven D'Aprano

unread,
Sep 26, 2012, 7:07:40 PM9/26/12
to python...@python.org
On 27/09/12 06:02, Mark Dickinson wrote:
> On Wed, Sep 26, 2012 at 8:36 PM, M.-A. Lemburg<m...@egenix.com> wrote:
>> It's actually quite common in finance and time calculations to
>> round to the nearest say basis point, cent or say micro second
>> in calculations
>
> That's exactly where the problems creep in, though. Naive users
> expect rounding to give 'correct' results for decimal halfway cases,
> and then are surprised when it doesn't.
>
>>>> round(2.675, 2)
> 2.67
>
> So you end up explaining again and again that computing binary
> approximations to decimal rounds of binary approximations of decimal
> halfway cases is a bad idea.

Pretty much *everything* about binary floats is surprising to people
who expect decimal semantics. Unless we're going to make Decimal the
default floating point type, and shift binary floats to a module, I
don't see any way around that, and a particularly don't see any reason
to single round() out as more confusing than any of the other float
gotchas.

Speaking from my experience on the tutor@ and pytho...@python.org
mailing lists, I believe that problems with round are vanishingly rare,
probably an order of magnitude fewer than "why doesn't Python add my
two floats correctly?" type questions.



--
Steven

Raymond Hettinger

unread,
Sep 26, 2012, 7:47:57 PM9/26/12
to Steven D'Aprano, python...@python.org

On Sep 26, 2012, at 7:07 PM, Steven D'Aprano <st...@pearwood.info> wrote:

Pretty much *everything* about binary floats is surprising to people
who expect decimal semantics. Unless we're going to make Decimal the
default floating point type, and shift binary floats to a module, I
don't see any way around that, and a particularly don't see any reason
to single round() out as more confusing than any of the other float
gotchas.

Speaking from my experience on the tutor@ and pytho...@python.org
mailing lists, I believe that problems with round are vanishingly rare,
probably an order of magnitude fewer than "why doesn't Python add my
two floats correctly?" type questions.

My experience teaching and consulting is matches your experience on tutor.
I agree with your suggestion to leave round() untouched.


Raymond

Bill Janssen

unread,
Sep 26, 2012, 8:32:54 PM9/26/12
to python-ideas
MRAB <pyt...@mrabarnett.plus.com> wrote:

> If we're going to move 'round' into 'math' because it sometimes gives
> results which puzzle naive users, shouldn't we do the same to 'float'?
> :-)

Ah, but float is a type, not a function.

Bill

Ben Finney

unread,
Sep 26, 2012, 8:45:43 PM9/26/12
to python...@python.org
"M.-A. Lemburg" <m...@egenix.com> writes:

> Mark Dickinson wrote:
> >>>> round(2.675, 2)
> > 2.67
> >
> > So you end up explaining again and again that computing binary
> > approximations to decimal rounds of binary approximations of decimal
> > halfway cases is a bad idea.
>
> But that's the fault of round(), is it ? ;-) It's more one of
> educating people of what to expect when working with floats.

It's the fault of the two-parameter ‘round’, yes. It is an attractive
nuisance that appears to promise one thing but doesn't deliver, and
makes it easy to do the wrong thing by mistake.

Where feasible, and where it doesn't unreasonably restrict
functionality, IMO Python should make it difficult to do the wrong thing
by mistake.

> Your example is a typical case that comes up when people enter
> examples and wonder why they don't see the expected results.

I think this is an argument that deprecating, and eventually removing,
the two-parameter form of ‘round’, would be helpful overall.

--
\ “Consider the daffodil. And while you're doing that, I'll be |
`\ over here, looking through your stuff.” —Jack Handey |
_o__) |
Ben Finney

Calvin Spealman

unread,
Sep 26, 2012, 9:14:32 PM9/26/12
to Guido van Rossum, python-ideas
On Wed, Sep 26, 2012 at 2:55 PM, Guido van Rossum <gu...@python.org> wrote:
> On Wed, Sep 26, 2012 at 11:51 AM, Mike Graham <mikeg...@gmail.com> wrote:
>> The builtin round function is completely useless. I've never seen
>> anyone use it constructively. Usually people using it are new
>> programmers who are not comfortable with or aware of string
>> formatting. Sometimes people use it to poorly replicate functionality
>> that's implemented correctly in the decimal module.
>
> You're probably right. It has ancient ancestry: it was one of the
> functions I copied directly from ABC. (It's actually more useful now
> that floats are printed with minimal digits.)
>
> But given the pain of removing a builtin, is it worth it? maybe we can
> just document the better ways of accomplishing its tasks?

I think it is reasonable with the right justifications, deprecation period, and
obvious migration path.

Also, I'd be completely in support of dropping round() and agree it gets misused
and leads to too much confusion. We should promote the right ways, and some
times to show the right path you need to lock another door and throw
away the key.

> --
> --Guido van Rossum (python.org/~guido)
> _______________________________________________
> Python-ideas mailing list
> Python...@python.org
> http://mail.python.org/mailman/listinfo/python-ideas



--
Read my blog! I depend on your acceptance of my opinion! I am interesting!
http://techblog.ironfroggy.com/
Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy

Steven D'Aprano

unread,
Sep 26, 2012, 9:46:52 PM9/26/12
to python...@python.org
On 27/09/12 10:32, Bill Janssen wrote:
> MRAB<pyt...@mrabarnett.plus.com> wrote:
>
>> If we're going to move 'round' into 'math' because it sometimes gives
>> results which puzzle naive users, shouldn't we do the same to 'float'?
>> :-)
>
> Ah, but float is a type, not a function.

What difference does that make? Floats sometimes give results which puzzle
naive users.

py> L = [1/10]*10
py> print(L)
[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
py> sum(L) # should be 1.0
0.9999999999999999

"Why doesn't Python add up correctly?"

And so we have to explain that the float 0.1 is not actually 0.1 because
you can't represent 0.1 as a finite binary fraction, due to some fairly
subtle mathematics that goes right past most people. The float 0.1 is
actually a tiny bit *larger* than the decimal 0.1, but when you add ten of
them together, you end up with a number that it a tiny bit *smaller* than
the expected result.

Don't you just love binary floating point?

Matthew used a smiley there, but I think there is a very strong case for
making the default floating point numeric type Decimal rather than float.
Decimals behave more like people expect, and they interact better with
other numeric types (ints and Fractions) than floats.

Obviously this will be a big change, almost certainly requiring a PEP and
a long lead time, e.g. Decimal could become a built-in in Python 3.4, then
in 3.5 you could do "from __future__ import decimal_floats", and in 3.6 it
could be the standard behaviour, or perhaps a runtime flag to switch between
binary and decimal floats.

I hate to think how much work would be involved.



--
Steven

MRAB

unread,
Sep 26, 2012, 10:11:06 PM9/26/12
to python-ideas
On 2012-09-27 01:32, Bill Janssen wrote:
> MRAB <pyt...@mrabarnett.plus.com> wrote:
>
>> If we're going to move 'round' into 'math' because it sometimes gives
>> results which puzzle naive users, shouldn't we do the same to 'float'?
>> :-)
>
> Ah, but float is a type, not a function.
>
They are both (first-class) objects, aren't they? Why treat them
differently? Surely such discrimination is unPythonic? :-)

Steven D'Aprano

unread,
Sep 26, 2012, 10:15:41 PM9/26/12
to python...@python.org
On 27/09/12 11:14, Calvin Spealman wrote:
> On Wed, Sep 26, 2012 at 2:55 PM, Guido van Rossum<gu...@python.org> wrote:
>> On Wed, Sep 26, 2012 at 11:51 AM, Mike Graham<mikeg...@gmail.com> wrote:
>>> The builtin round function is completely useless. I've never seen
>>> anyone use it constructively. Usually people using it are new
>>> programmers who are not comfortable with or aware of string
>>> formatting. Sometimes people use it to poorly replicate functionality
>>> that's implemented correctly in the decimal module.
>>
>> You're probably right. It has ancient ancestry: it was one of the
>> functions I copied directly from ABC. (It's actually more useful now
>> that floats are printed with minimal digits.)
>>
>> But given the pain of removing a builtin, is it worth it? maybe we can
>> just document the better ways of accomplishing its tasks?
>
> I think it is reasonable with the right justifications, deprecation period, and
> obvious migration path.
>
> Also, I'd be completely in support of dropping round() and agree it gets misused
> and leads to too much confusion. We should promote the right ways, and some
> times to show the right path you need to lock another door and throw
> away the key.


I don't believe that round gets misused and causes confusion to any significant
degree. That belief is based on many years experience on two high-traffic mailing
lists with many beginners. I've seen plenty of examples of beginners confused that
Python can't add floats correctly, but if I've ever seen somebody confused by round,
it was so uncommon and so long ago I've forgotten it.

It seems to me that this proposal is based on a purely theoretical fear that some
people manage to escape being confused by the far more obvious floating point
gotchas[1] but can't understand round. There are much more common, and bigger,
surprises with binary floats than round, and it seems to me that depreciating it
just disrupts those who do use it for no real benefit.

So -1 on such a change.

I could be convinced to change that to a -0.5 if round were moved to the math module
exactly as is, including the second argument. But even that is a disruption for no
meaningful benefit.



[1] I managed to surprise myself the other week when I "discovered" what was obvious
in hindsight, that for sufficiently large values all finite floats are even integer
values. I had known the "integer value" part, but was surprised by the "even" part.
I shouldn't have been.


--
Steven

Mike Graham

unread,
Sep 27, 2012, 12:10:34 AM9/27/12
to Steven D'Aprano, Python-Ideas
On Wed, Sep 26, 2012 at 10:15 PM, Steven D'Aprano <st...@pearwood.info> wrote:
> I don't believe that round gets misused and causes confusion to any
> significant
> degree. That belief is based on many years experience on two high-traffic
> mailing
> lists with many beginners. I've seen plenty of examples of beginners
> confused that
> Python can't add floats correctly, but if I've ever seen somebody confused
> by round,
> it was so uncommon and so long ago I've forgotten it.
>
> It seems to me that this proposal is based on a purely theoretical fear that
> some
> people manage to escape being confused by the far more obvious floating
> point
> gotchas[1] but can't understand round. There are much more common, and
> bigger,
> surprises with binary floats than round, and it seems to me that
> depreciating it
> just disrupts those who do use it for no real benefit.

I don't have a "purely theoretical fear" regarding round; I simply
have had a different experience and analysis than you. I have long
been an active member of the official Python IRC channel and other
Python IRC channels and of various other support communities (I beat
StackOverflow before they added the new levels :) ). I have seen many,
many people have questions about round and they almost always don't
want to be using it. Most often, people really want to be using string
formatting, but there are all sorts of . I posted here today after yet
another person came into #python with a round question where they
didn't want round.

My problem with round isn't that new people don't understand it--it's
that there's nothing worth understanding. (With floats, the situation
merely requires education then people can use floats well. With round,
when you learn you stop using it.) round(x, n) for n>0 is quite simply
not sane code. rounding is an exact operation and it does not make any
sense to do base 10 rounding on base 2 numbers in this way. round for
n <= 0 is not so criminal, but it sometimes-inconveniently returns a
float and it's trivially written shorter/as-easily for n=0 and seldom
actually needed for n<0.

Mike

Greg Ewing

unread,
Sep 27, 2012, 6:23:20 AM9/27/12
to python...@python.org
Mark Adam wrote:
> Modules reside on file and are changeable, Namespaces solely in
> memory, defined by the Interpreter itself.

Presumably they would be implemented as module objects,
created automatically at interpreter startup instead of
being loaded from a file.

In which case "built-in module" might be a better term
for them. And their names should start with lower case.

Also you wouldn't need new syntax to get names out of
them, just the existing import machinery:

from numbers import *

--
Greg

Gregory P. Smith

unread,
Sep 30, 2012, 5:38:33 PM9/30/12
to python...@python.org
Why suggest adding new round-like functions to the math module rather than defining a new round method on all numerical objects?

-gps

Joshua Landau

unread,
Sep 30, 2012, 5:48:21 PM9/30/12
to Gregory P. Smith, python...@python.org
On 30 September 2012 22:38, Gregory P. Smith <gr...@krypto.org> wrote:
Why suggest adding new round-like functions to the math module rather than defining a new round method on all numerical objects?

 >>> round("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type str doesn't define __round__ method

It seems it is done like that already ;)
This seems like a problem for the proposal, though: we can't have it in the math library if it's a method!

Joshua Landau

unread,
Sep 30, 2012, 5:51:30 PM9/30/12
to Gregory P. Smith, python...@python.org
On 30 September 2012 22:48, Joshua Landau <joshua.l...@gmail.com> wrote:
This seems like a problem for the proposal, though: we can't have it in the math library if it's a method!

Now I think about it: yeah, it can be. We just coerce to float/decimal first. *sigh*

Case Van Horsen

unread,
Sep 30, 2012, 6:08:07 PM9/30/12
to Joshua Landau, python...@python.org
math.ceil(x), math.floor(x), and math.trunc(x) and round(x) already
call the special methods x.__ceil__, x.__floor__, x.__round__, and
x.__trunc__. So those four functions already work with decimal
instances (and other numeric types that support those methods.)

casevh

Joshua Landau

unread,
Sep 30, 2012, 6:19:33 PM9/30/12
to Case Van Horsen, python...@python.org
On 30 September 2012 23:08, Case Van Horsen <cas...@gmail.com> wrote:
On Sun, Sep 30, 2012 at 2:51 PM, Joshua Landau
<joshua.l...@gmail.com> wrote:
> On 30 September 2012 22:48, Joshua Landau <joshua.l...@gmail.com>
> wrote:
>>
>> This seems like a problem for the proposal, though: we can't have it in
>> the math library if it's a method!
>
>
> Now I think about it: yeah, it can be. We just coerce to float/decimal
> first. *sigh*
math.ceil(x), math.floor(x), and math.trunc(x) and round(x) already
call the special methods x.__ceil__, x.__floor__, x.__round__, and
x.__trunc__. So those four functions already work with decimal
instances (and other numeric types that support those methods.)

 >>> math.ceil("")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: a float is required

How deceptive... I hope you forgive me for not realizing that (even though I must have seen the __ceil__ and __floor__ methods a thousand times).
OK, carry on.

Steven D'Aprano

unread,
Sep 30, 2012, 9:44:36 PM9/30/12
to python...@python.org
On Sun, Sep 30, 2012 at 02:38:33PM -0700, Gregory P. Smith wrote:
> Why suggest adding new round-like functions to the math module rather than
> defining a new round method on all numerical objects?

round already calls the special __round__ method, and in 3.2 works with
ints, floats, Decimals and Fractions. Only complex misses out.

py> round(12345, -2)
12300
py> from decimal import Decimal as D
py> round(D("1.2345"), 2)
Decimal('1.23')
py> from fractions import Fraction as F
py> round(F(12345, 10000), 2)
Fraction(123, 100)



--
Steven

Terry Reedy

unread,
Sep 30, 2012, 11:17:55 PM9/30/12
to python...@python.org
On 9/30/2012 6:19 PM, Joshua Landau wrote:

> >>> math.ceil("")
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: *a float is required*
>
>
> How deceptive... I hope you forgive me for not realizing that (even
> though I must have seen the __ceil__ and __floor__ methods a thousand
> times).
> OK, carry on.

The obsolete error message should be fixed. A number is required. Or
perhaps 'float or number with __ceil__ method'.

--
Terry Jan Reedy

Mark Adam

unread,
Oct 1, 2012, 12:46:05 AM10/1/12
to Greg Ewing, python...@python.org
On Thu, Sep 27, 2012 at 5:23 AM, Greg Ewing <greg....@canterbury.ac.nz> wrote:
> Presumably they would be implemented as module objects,
> created automatically at interpreter startup instead of
> being loaded from a file.
>
> In which case "built-in module" might be a better term
> for them. And their names should start with lower case.

That's cool. YES, lowercase.

> Also you wouldn't need new syntax to get names out of
> them, just the existing import machinery:
>
> from numbers import *

Well, to me there must be a clear partitioning.

The stuff in the builtin [module] sets the tone for the whole
interpreter environment (and I think python culture itself). If one
were to use the standard import language (like in your example), it
confuses one "semantically" -- because you're suggesting to treat a it
(i.e. a whole class of "things") as something optional.

Does that make sense? Thanks,

markj

Steven D'Aprano

unread,
Oct 1, 2012, 2:05:51 AM10/1/12
to python...@python.org
On Sun, Sep 30, 2012 at 11:46:05PM -0500, Mark Adam wrote:
> On Thu, Sep 27, 2012 at 5:23 AM, Greg Ewing <greg....@canterbury.ac.nz> wrote:
> > Presumably they would be implemented as module objects,
> > created automatically at interpreter startup instead of
> > being loaded from a file.
> >
> > In which case "built-in module" might be a better term
> > for them. And their names should start with lower case.
>
> That's cool. YES, lowercase.

I'm not sure why "built-in module" is a better term for something which
I gather is a separate namespace within a module, so you can have:

module.spam # global namespace
module.sub.spam # sub is a "submodule" or "namespace"

but sub has no independent existence as a file on disk. If that's what
we're discussing, I don't think that "built-in module" is a good name,
since it isn't *built-in*.

We already have something called "built-in modules" -- modules like sys
which actually are built-in to the Python virtual machine.



> > Also you wouldn't need new syntax to get names out of
> > them, just the existing import machinery:
> >
> > from numbers import *
>
> Well, to me there must be a clear partitioning.
>
> The stuff in the builtin [module] sets the tone for the whole
> interpreter environment (and I think python culture itself). If one
> were to use the standard import language (like in your example), it
> confuses one "semantically" -- because you're suggesting to treat a it
> (i.e. a whole class of "things") as something optional.
>
> Does that make sense?

Not to me, I'm afraid.



--
Steven

Antoine Pitrou

unread,
Oct 1, 2012, 7:57:46 AM10/1/12
to python...@python.org
On Wed, 26 Sep 2012 17:21:40 -0400
Daniel Holth <dho...@gmail.com> wrote:
> Normally deprecation means you keep it forever but don't mention it much in
> the docs...

Not really. Most deprecated things disappear one or two versions after
they are deprecated. We only keep something forever when removing it
would break a lot of code and keeping it is cheap.

Regards

Antoine.


--
Software development and contracting: http://pro.pitrou.net

Mark Adam

unread,
Oct 1, 2012, 12:12:46 PM10/1/12
to Steven D'Aprano, python...@python.org
On Mon, Oct 1, 2012 at 1:05 AM, Steven D'Aprano <st...@pearwood.info> wrote:
> I'm not sure why "built-in module" is a better term for something which
> I gather is a separate namespace within a module, so you can have:

Yeah, I'm not really sure it makes sense to call it a module at all.
I was sort of capitulating about the use of the word "module". It's
not like you can do "import __builtins__" in the interpreter, so if
one is going to call it a module (like the interpreter currently
does), one should see that it is a very special exception of the word.

I prefer "namespace", it's the built-in namespace which is a synonym
for "the global module".

>> Well, to me there must be a clear partitioning.
>>
>> The stuff in the builtin [module] sets the tone for the whole
>> interpreter environment (and I think python culture itself). If one
>> were to use the standard import language (like in your example), it
>> confuses one "semantically" -- because you're suggesting to treat a it
>> (i.e. a whole class of "things") as something optional.
>>
>> Does that make sense?
>
> Not to me, I'm afraid.

Hopefully the above makes it a little clearer. But, it's as if you're
going on a road trip, you want to travel efficient and light -- what
you include in your backpack ("interpreter environment") is your
"builtin" and everything else you'll "buy"/import on the road.
Modules are those things on the road.

mark

Nick Coghlan

unread,
Oct 1, 2012, 2:35:47 PM10/1/12
to Mark Adam, python...@python.org
On Mon, Oct 1, 2012 at 9:42 PM, Mark Adam <dreamin...@gmail.com> wrote:
> On Mon, Oct 1, 2012 at 1:05 AM, Steven D'Aprano <st...@pearwood.info> wrote:
>> I'm not sure why "built-in module" is a better term for something which
>> I gather is a separate namespace within a module, so you can have:
>
> Yeah, I'm not really sure it makes sense to call it a module at all.
> I was sort of capitulating about the use of the word "module". It's
> not like you can do "import __builtins__" in the interpreter, so if
> one is going to call it a module (like the interpreter currently
> does), one should see that it is a very special exception of the word.

"import __builtin__" in Python 2, "import builtins" in Python 3. The
contents of those modules are implicitly made available to all Python
code running in that process.

Cheers,
Nick.

--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia

Greg Ewing

unread,
Oct 1, 2012, 7:07:05 PM10/1/12
to python...@python.org
Mark Adam wrote:
> It's not like you can do "import __builtins__" in the interpreter,

But you *can* do "import __builtin__".

Also, "sys" is created at interpreter startup and doesn't correspond
to any disk file, but we don't seem to mind calling it a module and
using the same import syntax to access it.

The only difference I can see with these proposed namespace things is
that they would be pre-bound to names in the builtin namespace.

> But, it's as if you're
> going on a road trip, you want to travel efficient and light -- what
> you include in your backpack ("interpreter environment") is your
> "builtin" and everything else you'll "buy"/import on the road.
> Modules are those things on the road.

The sys module violates this taxonomy -- it's already in your
backpack, just tucked away in a paper bag that you need to open
first.

--
Greg

Boris Borcic

unread,
Oct 3, 2012, 8:52:43 AM10/3/12
to python...@python.org
Mike Graham wrote:
> round(x, n) for n>0 is quite simply not sane code.

I've occasionally used round(x,n) with n>0 - as a quick way to normalize away
numeric imprecisions and have values generated by a computation recognized as
identical set elements or dictionary keys. I'd have used a function to round in
binary instead of decimal had one been handy, but otoh I don't see it would make
a real difference, would it?
Reply all
Reply to author
Forward
0 new messages