Issue 27936: Inconsistent round behavior between float and int (original) (raw)

Created on 2016-09-02 06:52 by Jonatan Skogsfors, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
fix_round_default_none_with_test.diff rhettinger,2016-09-02 08:25 review
Messages (8)
msg274205 - (view) Author: Jonatan Skogsfors (Jonatan Skogsfors) Date: 2016-09-02 06:52
Theo error handling for round is different for float and int. Python 3.5.1 (default, Apr 18 2016, 11:46:32) [GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.29)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> round(1.0, None) 1 >>> round(1, None) Traceback (most recent call last): File "", line 1, in TypeError: 'NoneType' object cannot be interpreted as an integer
msg274208 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-09-02 08:13
The different data types make different choices: >>> from decimal import Decimal >>> from fractions import Fraction >>> (1).__round__(None) Traceback (most recent call last): File "<pyshell#39>", line 1, in (1).__round__(None) TypeError: 'NoneType' object cannot be interpreted as an integer >>> (1.0).__round__(None) 1 >>> Decimal(1).__round__(None) Traceback (most recent call last): File "<pyshell#41>", line 1, in Decimal(1).__round__(None) TypeError: optional arg must be an integer >>> Fraction(1, 1).__round__(None) 1 >>> from _pydecimal import Decimal >>> Decimal(1).__round__(None) 1 For Fraction and _pydecimal, the behavior comes from using None as a placeholder (which is common and normal in pure python code). For float there is explicit code to test for the None case. For int, the None test was omitted (perhaps a mistake) and the error is raised by PyNumber_Index. Looking through tests, only Lib/test/test_float.py tests for None being allowable. Elsewhere, it seems to be an implementation detail. The old Python 2 version of the round() function never let None be passed in (because it used PyArg_ParseTupleAndKeywords(args, kwds, "d|i:round"). That logic seems to get lost in the Python 3 version when __round__ was introduced. To resolve the differences, I think the round() function should explicitly check for None and replace it with zero before calling the underling __round__ functions where we would allow variable according the needs of the implementation.
msg274212 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2016-09-02 08:50
> I think the round() function should explicitly check for None and replace it with zero That would be a change in behaviour: `round(x)` is not the same as `round(x, 0)`. For most types, `round(x)` returns an `int`, while `round(x, 0)` returns something of the same type as `x`. Instead, I think we should add the check for `None` to `int`s `__round__` implementation. >>> round(1.3, 0) 1.0 >>> round(1.3) 1 >>> round(1.3, None) 1
msg274213 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2016-09-02 08:52
Ah, sorry; now that I've looked at the patch, I see I misunderstood. You're not replacing None with zero; you're replacing it with NULL. Patch LGTM.
msg274214 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2016-09-02 08:55
The test could be strengthened to add a check that the types of `round(x)` and `round(x, None)` match.
msg274265 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2016-09-02 17:44
For the record, the float behaviour was changed (for Python 3.5) in http://bugs.python.org/issue19933. There didn't seem to be any particularly strong motivation for that change, but it's done now.
msg274289 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-09-03 08:55
New changeset c3c4d8e4ca1a by Raymond Hettinger in branch '3.5': Issue 27936: Fix inconsistent round() behavior between float and int https://hg.python.org/cpython/rev/c3c4d8e4ca1a
msg274376 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-09-04 18:29
New changeset 7108f2a708c9 by Raymond Hettinger in branch '3.5': Issue 27936: Update doc for round() to indicate that None is an allowable argument. https://hg.python.org/cpython/rev/7108f2a708c9
History
Date User Action Args
2022-04-11 14:58:35 admin set github: 72123
2016-09-04 18:29:23 python-dev set messages: +
2016-09-03 08:57:57 rhettinger set status: open -> closedassignee: rhettingerresolution: fixedversions: + Python 3.6
2016-09-03 08:55:50 python-dev set nosy: + python-devmessages: +
2016-09-02 17:44:35 mark.dickinson set messages: +
2016-09-02 08:55:34 mark.dickinson set messages: +
2016-09-02 08:52:49 mark.dickinson set messages: +
2016-09-02 08:50:47 mark.dickinson set nosy: + mark.dickinsonmessages: +
2016-09-02 08:25:14 rhettinger set files: - fix_round_default_none.diff
2016-09-02 08:25:05 rhettinger set files: + fix_round_default_none_with_test.diff
2016-09-02 08:17:25 rhettinger set files: + fix_round_default_none.diffkeywords: + patch
2016-09-02 08:13:46 rhettinger set nosy: + rhettingermessages: +
2016-09-02 06:52:55 Jonatan Skogsfors create