1

I'm solving a small exercise from a beginners python book. I have to create a class Flower with three instance variables of type str, int, and float, that respectively represent the name of the flower, its number of petals, and its price. I also have to include methods for setting the value of each type, and retrieving the value of each type. I understand that the user can input any type he likes in the instance variables. For example, he might pass the number of petals to Flower instance as str and not as int. To avoid those problems I included simple try/except blocks in my class methods. Below is a working example:

class Flower:
    """A flower."""

    def __init__(self, name, petals, price):
        """Create a new flower instance.

        name    the name of the flower (e.g. 'Spanish Oyster')
        petals  the number of petals exists (e.g. 50)
        price   price of each flower (measured in euros)
        """
        self._name = str(name)
        self._petals = petals
        self._price = price

    def set_name(self, name):
        self._name = str(name)

    def get_name(self):
        return self._name

    def set_petals(self, petals):
        try:
            self._petals = int(petals, 10)
        except ValueError:
            print('set_petals(): could not parse "%s" to int().' % petals)

    def get_petals(self):
        return self._petals

    def set_price(self, price):
        try:
            self._price = float(price)
        except ValueError:
            print('set_price(): You should parse "%s" to float().' % price)

    def get_price(self):
        return self._price


if __name__ == '__main__':
    rose = Flower('Rose', 60, 1.3)

    print('%s contains %d petals costs %.2f euros.' % \
            (rose.get_name(), rose.get_petals(), rose.get_price()))

    rose.set_petals('error')


    """Initialize a new Flower instance with false values."""
    sunflower = Flower('Sunflower', 'error', 'another error')

    print('%s contains %d petals costs %.2f euros.' % \
            (sunflower.get_name(), sunflower.get_petals(), \
            sunflower.get_price()))

Explanation

Let's consider that a user initialize a new Flower instance:

rose = Flower('Rose', 60, 1.3)

Then he wants to update the number of petals, so he calls set_petals() method:

rose.set_petals('error')

My exception handling block catch this and prints:

set_petals(): could not parse "error" to int().

The same logic applies in set_price() method.

Now consider that he pass those false values to the constructor.

sunflower = Flower('Sunflower', 'error', 'another error')

In the constructor, as you see in my code, I don't check for type errors, so when I'm going to print the values from sunflower instance this is what I get in the output when I execute the second print:

TypeError: %d format: a number is required, not str

Problem

What I try to accomplish is to enter these type checks in the constructor as well. However, I'm new to python and do not know what is the best way to do it to keep the appropriate level of abstraction and not violate the DRY principle. One thought was to write try/except blocks in the constructor, but this would overwhelm my code. Another idea was to separate the error handling in different functions. How do I handle those type checks properly?

2
  • Interestingly, I have found two seemingly contradictory answers: here and here. Commented May 16, 2017 at 9:56
  • @IanS thank you very much. I check the links now. Commented May 16, 2017 at 9:57

1 Answer 1

4

Simply do this:

   def __init__(self, name, petals, price):
        """Create a new flower instance.

        name    the name of the flower (e.g. 'Spanish Oyster')
        petals  the number of petals exists (e.g. 50)
        price   price of each flower (measured in euros)
        """
        self._name = str(name)
        self.set_petals(petals)
        self.set_price(price)
Sign up to request clarification or add additional context in comments.

1 Comment

This was something I was curious about, but didn't knowing how to search it. Thank you very much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.