Reputation: 8540
I found this phrase in module fraction.py
of standard library:
class Fraction(numbers.Rational):
...
# We're immutable, so use __new__ not __init__
def __new__(cls, numerator=0, denominator=None, *, _normalize=True):
"""Constructs a Rational.
...
I am confused with it because Fraction
instance, strictly speaking, is not immutable:
import fractions
fraction = fractions.Fraction(3, 2)
fraction._numerator = 1 # it works
print(fraction) # 1/2
So, I'm asking for more clarification why __new__
is used instead of __init__
and what does this phrase mean here.
Upvotes: 2
Views: 112
Reputation: 281748
It's logically immutable, not enforced. It's basically impossible to really enforce immutability in Python. Crazier enforcement attempts can always be met with crazier bypasses. For example, there's a bit of "enforcement" in that numerator
and denominator
are properties with no setter, but you've already found the bypass for that.
If you really want to screw with a Fraction object, you can, and you can do a lot worse than setting _numerator
, but you're asking for problems.
Upvotes: 2