The proposed PR optimizes the Fraction constructor and statistics.mean() (and several other statistics functions) by using a private helper implemented in C which abstracts converting a number to an integer ratio.
$ ./python -m timeit -s "from fractions import Fraction as F" "F(123)"
500000 loops, best of 5: 655 nsec per loop
500000 loops, best of 5: 749 nsec per loop
$ ./python -m timeit -s "from fractions import Fraction as F" "F(1.23)"
200000 loops, best of 5: 1.29 usec per loop
200000 loops, best of 5: 1.03 usec per loop
$ ./python -m timeit -s "from fractions import Fraction as F; f = F(22, 7)" "F(f)"
200000 loops, best of 5: 1.17 usec per loop
500000 loops, best of 5: 899 nsec per loop
$ ./python -m timeit -s "from fractions import Fraction as F; from decimal import Decimal as D; d = D('1.23')" "F(d)"
200000 loops, best of 5: 1.64 usec per loop
200000 loops, best of 5: 1.29 usec per loop
$ ./python -m timeit -s "from statistics import mean; a = [1]*1000" "mean(a)"
500 loops, best of 5: 456 usec per loop
1000 loops, best of 5: 321 usec per loop
$ ./python -m timeit -s "from statistics import mean; a = [1.23]*1000" "mean(a)"
500 loops, best of 5: 645 usec per loop
500 loops, best of 5: 659 usec per loop
$ ./python -m timeit -s "from statistics import mean; from fractions import Fraction as F; a = [F(22, 7)]*1000" "mean(a)"
500 loops, best of 5: 637 usec per loop
500 loops, best of 5: 490 usec per loop
$ ./python -m timeit -s "from statistics import mean; from decimal import Decimal as D; a = [D('1.23')]*1000" "mean(a)"
500 loops, best of 5: 946 usec per loop
500 loops, best of 5: 915 usec per loop
There is a 14% regression in creating a Fraction from an integer, but for non-integer numbers it gains 25% speed up. The effect on statistics.mean() varies from insignificant to +40%. |