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?