Why I am getting the maximum recursion depth exceeded error in an f-string in python?

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:
Exception traceback

>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

Leave a Reply