[Tutor] How to extract numerator and denominator from fractions.Fraction(4, 32)?

eryksun eryksun at gmail.com
Mon Aug 5 22:50:19 CEST 2013


On Mon, Aug 5, 2013 at 10:34 AM, Richard D. Moores <rdmoores at gmail.com> wrote:
>>>>> f.numerator
>> 2
>>>>> f.denominator
>> 7
>
> Ah, better yet! Thanks! But where could I have found that in
> <http://docs.python.org/3/library/fractions.html#module-fractions>?

Start with help(fractions), dir(fractions), and
dir(fractions.Fraction). If that doesn't answer your question, then
scan over the source:

    >>> import fractions, inspect, pydoc
    >>> pydoc.pager(inspect.getsource(fractions))

A quick scan comes up with the following:

    __slots__ = ('_numerator', '_denominator')

    @property
    def numerator(a):
        return a._numerator

    @property
    def denominator(a):
        return a._denominator

    def __str__(self):
        """str(self)"""
        if self._denominator == 1:
            return str(self._numerator)
        else:
            return '%s/%s' % (self._numerator, self._denominator)

More interesting is the reason it uses a property without a setter,
which makes the fraction 'immutable' -- as long as you don't tamper
with the private attributes.

The numerator and denominator values are used to compute the
fraction's hash, such that the hash is the same for an equal number
(int, float, Fraction, Decimal). So a Fraction can be used as a dict
key:

    >>> frac = Fraction(1)
    >>> d = {frac: 1}
    >>> frac in d
    True

The key to fetch the value can be any equal number:

    >>> d[1], d[1.0], d[Decimal(1)], d[Fraction(1)]
    (1, 1, 1, 1)

The value has to be immutable because mutating it (and thus the hash)
would leave the dict in an inconsistent state:

    >>> frac._numerator = 2
    >>> list(d)[0] is frac
    True
    >>> frac in d
    False
    >>> Fraction(2) in d
    False
    >>> Fraction(1) in d
    False

After mutating the value, frac has the hash of Fraction(2), but it's
still at the position for  Fraction(1) in the dict's hash table.
Looking for frac or Fraction(2) just finds an empty slot. Looking for
Fraction(1) finds frac in the table, but since it could just be a hash
collision it has to check for equality -- but frac no longer equals
Fraction(1).


More information about the Tutor mailing list