I have a class Fraction whose init creates the instance variables self.num = num
and self.denom=denom
:
def __init__(self,num=0,denom=1):
assert isinstance(num, int), "Numerator and denominator must be an integer"
assert isinstance(denom, int), "Numerator and denominator must be an integer"
assert denom != 0, "Denominator cannot be 0."
self.num = num
self.denom = denom
and I'm trying to write its __setattr__
method to prohibit changes to the instance variables once they have been initialized by raising a NameError:
def __setattr__(self,name,value):
if name not in Fraction.__dict__:
self.__dict__[name] = value
else:
raise NameError
From printing Fraction.__dict__
, I can see that the dict contains Fractions methods, rather than num,denom and their respective values. So I then tried to do: if name not in Fraction().__dict__:
and I ended up with a infinite recursion error. How can I access the dictionary that contains the instance variables?
You should use __slots__
instead to limit attributes to only those you want.
https://docs.python.org/3/reference/datamodel.html#slots
__slots__
allow us to explicitly declare data members (like properties) and deny the creation of__dict__
and__weakref__
(unless explicitly declared in__slots__
or available in a parent.)
[...] Without a
__dict__
variable, instances cannot be assigned new variables not listed in the__slots__
definition. Attempts to assign to an unlisted variable name raisesAttributeError
. [...]
So basically in your class add this, preferably somewhere at the top (just after class
line and before init):
__slots__ = 'num', 'denom'
And remove your setattr :)