I am getting the maximum recursion depth error which originates in an f-string. I am a newbie in Python and am not getting what’s going wrong. Any help will be highly appreciated.
Also, guide me if I am writing the constructor properly?
class NearEarthObject:
"""This class represents a near earth object"""
def __init__(self, designation, name, diameter, hazardous, approaches):
designation = designation
name = name
diameter = diameter
hazardous = hazardous
approaches = approaches
self.fullname = designation + "(" + name + ")"
if len(name) == 0:
self.fullname = designation
@property
def designation(self):
return self.designation
@designation.setter
def designation(self, designation):
self.designation = designation
@property
def name(self):
return self.name
@name.setter
def name(self,name):
self.name = name
@property
def diameter(self):
return self.diameter
@diameter.setter
def diameter(self,diameter):
self.diameter = diameter
@property
def hazardous(self):
return self.hazardous
@hazardous.setter
def hazardous(self, hazardous):
self.hazardous = hazardous
@property
def approaches(self):
return self.approaches
@approaches.setter
def approaches(self, approaches):
self.approaches = approaches
def __str__(self):
return f'NEO {self.fullname} has a diameter of {self.diameter:.3f} ' \
f'km and {"is" if self.hazardous == True else "is not"} potentially hazardous'
The exception traceback is here:
>Solution :
your properties are all written in a a way that will cause infinite recursion if you access them because you are using the same name for the property as you are for the underlying attribute
for example for the property diameter:
@property
def diameter(self):
return self.diameter
if you run the code
print(object.diameter)
when it tries to determine the value of object.diameter
it will run the diameter(self)
function which then tries to determine the value of the self.diameter
which again invokes the diameter(self)
function, which tries to determine the value of self.diameter
, etc etc until you reach recursion limit
When you create a property (eg. diameter
) you need to pick a new name for the actual attribute. A common choice is to use the same name with a single underscore in front of it. eg. _diameter
so your diameter property would be re-written as:
@property
def diameter(self):
"""provide the value of the diameter property by returning
the underlying _diameter attribute"""
return self._diameter
then you would also need to change your __init__
function to set the _diameter
attribute.
Additionally you could also create writable versions of your properties, in which case you would NOT need to change your __init__()
. You can create the readable and writable properties like this:
# create the readable property first
@property
def diameter(self):
"""provide the value of the diameter property by returning
the underlying _diameter attribute"""
return self._diameter
# then use the newly created diameter property's setter attribute
# to decorate a second function WITH THE SAME NAME which will be
# the setter
@diameter.setter
def diameter(self, new_diameter):
"""write to the diameter property by updating the value of
the underlying _diameter attribute"""
_diameter = new_diameter