Author veky
Recipients veky
Date 2016-08-23.08:39:40
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1471941581.22.0.742866227558.issue27832@psf.upfronthosting.co.za>
In-reply-to
Content
During the discussion about http://bugs.python.org/issue27539, we found the following weird behavior:

    >>> from fractions import Fraction as F
    >>> F(2, 3, 4)
    Fraction(2, 3)

It looks like the third argument is simply disregarded, but it's not so: if it's false, the fraction is not normalized, and it breaks a lot of arithmetic assumptions.

    >>> F(4, 2, 0)
    Fraction(4, 2)
    >>> _ == 2
    False

The secret is additional argument "_normalize" to Fraction.__new__, which was added for optimization in various cases (where we know that numerator and denominator are relatively prime, so the gcd needn't be computed). That argument was obviously meant for internal use only (its name starts with '_'), so accepting the above forms can be viewed as a bug. Although cases can be made for being able to set that argument from the outside, surely in most cases people passing 3 arguments are doing it by accident, not on purpose.

That bug is easily fixed, by declaring the argument as keyword only. The line 84 in lib/fractions.py should be changed from

-     def __new__(cls, numerator=0, denominator=None, _normalize=True):

to

+     def __new__(cls, numerator=0, denominator=None, *, _normalize=True):

That way, those who know what they are doing, can still pass the _normalize argument, but it's much harder to accidentally pass it for people who don't know nor care about it.

Of course, all the code from that file already passes _normalize by keyword, so no other code should be changed.
History
Date User Action Args
2016-08-23 08:39:41vekysetrecipients: + veky
2016-08-23 08:39:41vekysetmessageid: <1471941581.22.0.742866227558.issue27832@psf.upfronthosting.co.za>
2016-08-23 08:39:41vekylinkissue27832 messages
2016-08-23 08:39:40vekycreate