Как локально переопределить __truediv__ для возврата дроби

В Python 3 деление целых чисел или что-либо, включая число с плавающей точкой, приводит к плавающей точке:

>>> from fractions import Fraction
>>> f = Fraction(1, 2)
>>> f / 2
Fraction(1, 4)
>>> 2 / f
Fraction(4, 1)
>>> 1 / 2 
0.5
>>> 2 / 1 
2.0
>>> f / .1
5.0
>>> f / .2
2.5
>>> .2 / f
0.4

Я хотел бы получить деление для возврата дроби, то есть получить следующее поведение:

>>> 1 / 2
Fraction(1, 2)
>>> 2 / 1
Fraction(2, 1)

Я безуспешно пытался переопределить разделение:

>>> int.__truediv__ = lambda self, other: Fraction(self) / Fraction(other)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'int'

Какие у меня варианты? Я в порядке с введением MyFraction класс, полученный из фракции. По крайней мере, я хотел бы иметь возможность определить dictподобный класс X такой, что

>>> X({'a': 1/3}) == X({'a': Fraction(1, 3)})
True

NB. Похоже, что первоначально описанное мной поведение было намеченным (см. PEP 238):

Если и когда в Python добавляется рациональный тип (см. PEP 239), истинное деление для целых и длинных значений, вероятно, должно возвращать рациональное. Это позволяет избежать проблем с истинным разделением целых и приводит к потере информации. Но до тех пор, для последовательности, float является единственным выбором для истинного разделения.

1 ответ

Решение

Вы, вероятно, не должны этого делать, но вы можете встроить типы обезьяны-патча с помощью модуля Forbidden Fruit.

Другие вопросы по тегам