Faery
Faery

Reputation: 4650

Validate values when setting them and in constructor - Python 3.3

I have a design issue in Python, but I'm not very advanced neither in the language, nor in design, nor in Exceptions.

Here is what I want: I have a class with attributes like name, budget, ... and I want to be impossible to create object with lets say name shorter than 3 symbols and budget < 0. Also I want when changing some of this values, they to be checked again. If you try to create an object which doesn't meet this conditions, I want exception to be thrown.

Here is what I tried:

def __init__(self, name, budget):
    try:
        self.set_name(name)
        self.set_budget(budget)
    except Exception as e:
        print(e)
        return None

def set_name(name):
    if len(name) < 3:
        raise Exception("short name")
    else:
        self.__name = name

But here I have two problems :( The first one is that even when I try to create object with the name 'a' for example it IS created :( and I don't want invalid objects to be created. The second problem is that I have print in my init method and I don't want to have any I/O functions in it. But then how to get the message? How to get from the constructor what is the reason for not creating the object?

Also, this is for a very simple task and I don't want to overdo it with sophisticated and too long and hard solution :(

Can you please help me? Thank you very much in advance! :)

Upvotes: 3

Views: 1913

Answers (1)

Adam Smith
Adam Smith

Reputation: 54223

this is for a very simple task and I don't want to overdo it with sophisticated and too long and hard solution

This is the cause of so much gloom and doom in the IT world right now ahem Heartbleed but okay, we'll keep it simple :)

You want to confirm that len(name) >= 3 and budget >= 0, is that right? Let's do it then:

class Dummy(object):
    def __init__(self, name, budget):
        self.name = name
        self.budget = budget
    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self,value):
        self.validatename(value)
        self.__name = value
    @property
    def budget(self):
        return self.__budget
    @budget.setter
    def budget(self,value):
        self.validatebudget(value)
        self.__budget = value

    def validatename(self,value):
        if len(value) < 3:
            raise Exception("Some descriptive error here")
    def validatebudget(self,value):
        if isinstance(value,str):
            value = float(value) # this is more common than you'd think
        if value < 0:
            raise Exception("Some descriptive error here")

This is creating a function to validate each name and budget, which throw exceptions (intentionally uncaught in the class, though you could certainly prompt for that if you want!) if the value is wrong. This is not the best way to do it, but as per your quote at the top of my answer, it's the simplest way. It also utilizes python properties (SO question related here) to define a custom functions to handle getting and setting name and budget. Let's run an example:

>>> testobj = Dummy("Adam",100000)
# no error
>>> testobj.name
"Adam"
>>> testobj.budget
100000
>>> testobj.name = "Brian"
>>> testobj.name
"Brian"
>>> testobj.name = "Ed"
Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    testobj.name = "Ed"
  File "<pyshell#34>", line 12, in name
    self.validatename(value)
  File "<pyshell#34>", line 24, in validatename
    raise Exception("Some descriptive error here")
Exception: Some descriptive error here

Upvotes: 3

Related Questions